Merge branch 'MDL-73899-master' of https://github.com/andrewnicols/moodle

This commit is contained in:
Jake Dallimore 2022-03-10 15:34:21 +08:00
commit a745a7dfae
24 changed files with 733 additions and 620 deletions

View file

@ -1,5 +1,4 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
@ -15,34 +14,32 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Context\ContextClass;
use Behat\Behat\Context\ContextClass\ClassResolver as Resolver;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Moodle behat context class resolver. * Moodle behat context class resolver.
* *
* @package behat
* @copyright 2104 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Context\ContextClass;
use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler;
use Behat\Behat\Context\ContextClass\ClassResolver as Resolver;
/**
* Resolves arbitrary context strings into a context classes. * Resolves arbitrary context strings into a context classes.
* *
* @see ContextEnvironmentHandler * @see ContextEnvironmentHandler
* *
* @author Konstantin Kudryashov <ever.zet@gmail.com> * @package core
* @copyright 2104 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class ClassResolver implements Resolver { final class ClassResolver implements Resolver {
/** /** @var array keep list of all behat contexts in moodle. */
* @var array keep list of all behat contexts in moodle.
*/
private $moodlebehatcontexts = null; private $moodlebehatcontexts = null;
/** /**
* @param $parameters array list of params provided to moodle. * Constructor for ClassResolver class.
*
* @param array $parameters list of params provided to moodle.
*/ */
public function __construct($parameters) { public function __construct($parameters) {
$this->moodlebehatcontexts = $parameters['steps_definitions']; $this->moodlebehatcontexts = $parameters['steps_definitions'];
@ -51,19 +48,17 @@ final class ClassResolver implements Resolver {
* Checks if resolvers supports provided class. * Checks if resolvers supports provided class.
* Moodle behat context class starts with behat_ * Moodle behat context class starts with behat_
* *
* @param string $contextString * @param string $contextstring
*
* @return Boolean * @return Boolean
*/ */
public function supportsClass($contextString) { public function supportsClass($contextstring) {
return (strpos($contextString, 'behat_') === 0); return (strpos($contextstring, 'behat_') === 0);
} }
/** /**
* Resolves context class. * Resolves context class.
* *
* @param string $contexclass * @param string $contextclass
*
* @return string context class. * @return string context class.
*/ */
public function resolveClass($contextclass) { public function resolveClass($contextclass) {
@ -72,11 +67,13 @@ final class ClassResolver implements Resolver {
} }
// Using the key as context identifier load context class. // Using the key as context identifier load context class.
if (!empty($this->moodlebehatcontexts[$contextclass]) && if (
(file_exists($this->moodlebehatcontexts[$contextclass]))) { !empty($this->moodlebehatcontexts[$contextclass]) &&
(file_exists($this->moodlebehatcontexts[$contextclass]))
) {
require_once($this->moodlebehatcontexts[$contextclass]); require_once($this->moodlebehatcontexts[$contextclass]);
} else { } else {
throw new \RuntimeException('Moodle behat context "'.$contextclass.'" not found'); throw new \RuntimeException('Moodle behat context "' . $contextclass . '" not found');
} }
return $contextclass; return $contextclass;
} }

View file

@ -1,27 +1,41 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Context\Initializer; namespace Moodle\BehatExtension\Context\Initializer;
use Moodle\BehatExtension\Context\MoodleContext;
use Behat\Behat\Context\Initializer\ContextInitializer;
use Behat\Behat\Context\Context; use Behat\Behat\Context\Context;
use Behat\Behat\Context\Initializer\ContextInitializer;
use Moodle\BehatExtension\Context\MoodleContext;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* MoodleContext initializer * MoodleContext initializer
* *
* @package core
* @author David Monllaó <david.monllao@gmail.com> * @author David Monllaó <david.monllao@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class MoodleAwareInitializer implements ContextInitializer class MoodleAwareInitializer implements ContextInitializer {
{ /** @var array The list of parameters */
private $parameters; private $parameters;
/** /**
* Initializes initializer. * Initializes initializer.
* *
* @param Mink $mink
* @param array $parameters * @param array $parameters
*/ */
public function __construct(array $parameters) { public function __construct(array $parameters) {
@ -34,7 +48,7 @@ class MoodleAwareInitializer implements ContextInitializer
* @param Context $context * @param Context $context
*/ */
public function initializeContext(Context $context) { public function initializeContext(Context $context) {
if (method_exists($context, 'setMoodleConfig')) { if ($context instanceof MoodleContext) {
$context->setMoodleConfig($this->parameters); $context->setMoodleConfig($this->parameters);
} }
} }

View file

@ -1,31 +1,46 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Context; namespace Moodle\BehatExtension\Context;
use Behat\MinkExtension\Context\RawMinkContext; use Behat\MinkExtension\Context\RawMinkContext;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Moodle contexts loader * Moodle contexts loader
* *
* It gathers all the available steps definitions reading the * It gathers all the available steps definitions reading the
* Moodle configuration file * Moodle configuration file
* *
* @package core
* @copyright 2012 David Monllaó * @copyright 2012 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class MoodleContext extends RawMinkContext { class MoodleContext extends RawMinkContext {
/** /** @var array Moodle features and steps definitions list */
* Moodle features and steps definitions list protected $moodleconfig;
* @var array
*/
protected $moodleConfig;
/** /**
* Includes all the specified Moodle subcontexts * Includes all the specified Moodle subcontexts.
*
* @param array $parameters * @param array $parameters
*/ */
public function setMoodleConfig($parameters) { public function setMoodleConfig(array $parameters): void {
$this->moodleConfig = $parameters; $this->moodleconfig = $parameters;
} }
} }

View file

@ -14,18 +14,18 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Override step tester to ensure chained steps gets executed.
*
* @package behat
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Context\Step; namespace Moodle\BehatExtension\Context\Step;
use Behat\Gherkin\Node\StepNode; use Behat\Gherkin\Node\StepNode;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Base ChainedStep class. * Chained Step base class.
*
* @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
abstract class ChainedStep extends StepNode { abstract class ChainedStep extends StepNode {
/** /**
@ -33,16 +33,20 @@ abstract class ChainedStep extends StepNode {
*/ */
private $language; private $language;
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod.Found
/** /**
* Initializes ChainedStep. * Initializes ChainedStep.
* *
* @param string $type * @param string $keyword
* @param string $text * @param string $text
* @param array $arguments * @param array $arguments
* @param int $line
* @param string $keywordtype
*/ */
public function __construct($keyword, $text, array $arguments, $line = 0, $keywordType = 'Given') { public function __construct($keyword, $text, array $arguments, $line = 0, $keywordtype = 'Given') {
parent::__construct($keyword, $text, $arguments, $line, $keywordType); parent::__construct($keyword, $text, $arguments, $line, $keywordtype);
} }
// phpcs:enable Generic.CodeAnalysis.UselessOverridingMethod.Found
/** /**
* Sets language. * Sets language.

View file

@ -14,18 +14,15 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Context\Step;
/** /**
* Override step tester to ensure chained steps gets executed. * Chained `Given` step.
* *
* @package behat * @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com> * @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace Moodle\BehatExtension\Context\Step;
/**
* Given sub-step.
*/
class Given extends ChainedStep { class Given extends ChainedStep {
/** /**
* Initializes `Given` sub-step. * Initializes `Given` sub-step.

View file

@ -14,17 +14,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Override step tester to ensure chained steps gets executed.
*
* @package behat
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Context\Step; namespace Moodle\BehatExtension\Context\Step;
/** /**
* `Then` ChainedStep. * Chained `Then` ChainedStep.
*
* @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class Then extends ChainedStep { class Then extends ChainedStep {
/** /**

View file

@ -14,17 +14,15 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Context\Step;
/** /**
* Override step tester to ensure chained steps gets executed. * Chained `When` step.
* *
* @package behat * @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com> * @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace Moodle\BehatExtension\Context\Step;
/**
* `When` ChainedStep.
*/
class When extends ChainedStep { class When extends ChainedStep {
/** /**
* Initializes `When` sub-step. * Initializes `When` sub-step.

View file

@ -1,5 +1,4 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
@ -18,11 +17,10 @@
namespace Moodle\BehatExtension\Definition\Cli; namespace Moodle\BehatExtension\Definition\Cli;
use Behat\Behat\Definition\DefinitionWriter; use Behat\Behat\Definition\DefinitionWriter;
use Moodle\BehatExtension\Definition\Printer\ConsoleDefinitionInformationPrinter;
use Behat\Behat\Definition\Printer\ConsoleDefinitionListPrinter; use Behat\Behat\Definition\Printer\ConsoleDefinitionListPrinter;
use Behat\Behat\Definition\Printer\DefinitionPrinter;
use Behat\Testwork\Cli\Controller; use Behat\Testwork\Cli\Controller;
use Behat\Testwork\Suite\SuiteRepository; use Behat\Testwork\Suite\SuiteRepository;
use Moodle\BehatExtension\Definition\Printer\ConsoleDefinitionInformationPrinter;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@ -31,50 +29,47 @@ use Symfony\Component\Console\Output\OutputInterface;
/** /**
* Available definition controller, for calling moodle information printer. * Available definition controller, for calling moodle information printer.
* *
* @package behat * @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com> * @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class AvailableDefinitionsController implements Controller { final class AvailableDefinitionsController implements Controller {
/** /** @var SuiteRepository */
* @var SuiteRepository private $suiterepository;
*/
private $suiteRepository; /** @var DefinitionWriter */
/**
* @var DefinitionWriter
*/
private $writer; private $writer;
/**
* @var ConsoleDefinitionListPrinter /** @var ConsoleDefinitionListPrinter */
*/ private $listprinter;
private $listPrinter;
/** /** @var ConsoleDefinitionInformationPrinter */
* @var ConsoleDefinitionInformationPrinter private $infoprinter;
*/
private $infoPrinter;
/** /**
* Initializes controller. * Initializes controller.
* *
* @param SuiteRepository $suiteRepository * @param SuiteRepository $suiterepository
* @param DefinitionWriter $writer * @param DefinitionWriter $writer
* @param ConsoleDefinitionListPrinter $listPrinter * @param ConsoleDefinitionListPrinter $listprinter
* @param ConsoleDefinitionInformationPrinter $infoPrinter * @param ConsoleDefinitionInformationPrinter $infoprinter
*/ */
public function __construct( public function __construct(
SuiteRepository $suiteRepository, SuiteRepository $suiterepository,
DefinitionWriter $writer, DefinitionWriter $writer,
ConsoleDefinitionListPrinter $listPrinter, ConsoleDefinitionListPrinter $listprinter,
ConsoleDefinitionInformationPrinter $infoPrinter ConsoleDefinitionInformationPrinter $infoprinter
) { ) {
$this->suiteRepository = $suiteRepository; $this->suiterepository = $suiterepository;
$this->writer = $writer; $this->writer = $writer;
$this->listPrinter = $listPrinter; $this->listprinter = $listprinter;
$this->infoPrinter = $infoPrinter; $this->infoprinter = $infoprinter;
} }
/** /**
* {@inheritdoc} * Configures command to be executable by the controller.
*
* @param Command $command
*/ */
public function configure(Command $command) { public function configure(Command $command) {
$command->addOption('--definitions', '-d', InputOption::VALUE_REQUIRED, $command->addOption('--definitions', '-d', InputOption::VALUE_REQUIRED,
@ -87,15 +82,20 @@ final class AvailableDefinitionsController implements Controller {
} }
/** /**
* {@inheritdoc} * Executes controller.
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return null|integer
*/ */
public function execute(InputInterface $input, OutputInterface $output) { public function execute(InputInterface $input, OutputInterface $output) {
if (null === $argument = $input->getOption('definitions')) { if (null === $argument = $input->getOption('definitions')) {
return null; return null;
} }
$printer = $this->getDefinitionPrinter($argument); $printer = $this->getdefinitionPrinter($argument);
foreach ($this->suiteRepository->getSuites() as $suite) { foreach ($this->suiterepository->getSuites() as $suite) {
$this->writer->printSuiteDefinitions($printer, $suite); $this->writer->printSuiteDefinitions($printer, $suite);
} }
@ -107,17 +107,17 @@ final class AvailableDefinitionsController implements Controller {
* *
* @param string $argument * @param string $argument
* *
* @return DefinitionPrinter * @return \Behat\Behat\Definition\Printer\DefinitionPrinter
*/ */
private function getDefinitionPrinter($argument) { private function getdefinitionprinter($argument) {
if ('l' === $argument) { if ('l' === $argument) {
return $this->listPrinter; return $this->listprinter;
} }
if ('i' !== $argument) { if ('i' !== $argument) {
$this->infoPrinter->setSearchCriterion($argument); $this->infoprinter->setSearchCriterion($argument);
} }
return $this->infoPrinter; return $this->infoprinter;
} }
} }

View file

@ -1,5 +1,4 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
@ -17,23 +16,23 @@
namespace Moodle\BehatExtension\Definition\Printer; namespace Moodle\BehatExtension\Definition\Printer;
use Behat\Behat\Definition\Definition;
use Behat\Testwork\Suite\Suite;
use Behat\Behat\Definition\Printer\ConsoleDefinitionPrinter; use Behat\Behat\Definition\Printer\ConsoleDefinitionPrinter;
use Behat\Testwork\Suite\Suite;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Moodle console definition information printer. * Moodle console definition information printer.
*
* Used in moodle for definition printing. * Used in moodle for definition printing.
* *
* @package behat * @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com> * @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class ConsoleDefinitionInformationPrinter extends ConsoleDefinitionPrinter { final class ConsoleDefinitionInformationPrinter extends ConsoleDefinitionPrinter {
/** /** @var null|string */
* @var null|string private $searchcriterion;
*/
private $searchCriterion;
/** /**
* Sets search criterion. * Sets search criterion.
@ -41,11 +40,14 @@ final class ConsoleDefinitionInformationPrinter extends ConsoleDefinitionPrinter
* @param string $criterion * @param string $criterion
*/ */
public function setSearchCriterion($criterion) { public function setSearchCriterion($criterion) {
$this->searchCriterion = $criterion; $this->searchcriterion = $criterion;
} }
/** /**
* {@inheritdoc} * Prints definition.
*
* @param Suite $suite
* @param Definition[] $definitions
*/ */
public function printDefinitions(Suite $suite, $definitions) { public function printDefinitions(Suite $suite, $definitions) {
$template = <<<TPL $template = <<<TPL
@ -55,7 +57,7 @@ final class ConsoleDefinitionInformationPrinter extends ConsoleDefinitionPrinter
</div> </div>
TPL; TPL;
$search = $this->searchCriterion; $search = $this->searchcriterion;
// If there is a specific type (given, when or then) required. // If there is a specific type (given, when or then) required.
if (strpos($search, '&&') !== false) { if (strpos($search, '&&') !== false) {
@ -71,7 +73,7 @@ TPL;
$pattern = $definition->getPattern(); $pattern = $definition->getPattern();
if ($search && !preg_match('/'.str_replace(' ', '.*', preg_quote($search, '/').'/'), $pattern)) { if ($search && !preg_match('/' . str_replace(' ', '.*', preg_quote($search, '/') . '/'), $pattern)) {
continue; continue;
} }
@ -85,14 +87,16 @@ TPL;
'/"\(\?P<([^>]*)>(.*?)"( |$)/', '/"\(\?P<([^>]*)>(.*?)"( |$)/',
function ($matches) { function ($matches) {
return '"' . strtoupper($matches[1]) . '" '; return '"' . strtoupper($matches[1]) . '" ';
}, $pattern); },
$pattern
);
$definitiontoprint[] = strtr($template, array( $definitiontoprint[] = strtr($template, [
'{regex}' => $pattern, '{regex}' => $pattern,
'{type}' => str_pad($definition->getType(), 5, ' ', STR_PAD_LEFT), '{type}' => str_pad($definition->getType(), 5, ' ', STR_PAD_LEFT),
'{description}' => $description ? $description : '', '{description}' => $description ? $description : '',
'{apipath}' => $definition->getPath() '{apipath}' => $definition->getPath()
)); ]);
$this->write(implode("\n", $definitiontoprint)); $this->write(implode("\n", $definitiontoprint));
unset($definitiontoprint); unset($definitiontoprint);

View file

@ -1,16 +1,34 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Driver; namespace Moodle\BehatExtension\Driver;
use Behat\Mink\Session;
use OAndreyev\Mink\Driver\WebDriver as UpstreamDriver; use OAndreyev\Mink\Driver\WebDriver as UpstreamDriver;
use WebDriver\Key as key;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* WebDriver Driver to allow extra selenium capabilities required by Moodle. * WebDriver Driver to allow extra selenium capabilities required by Moodle.
*
* @package core
* @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class WebDriver extends UpstreamDriver class WebDriver extends UpstreamDriver {
{
/** /**
* Dirty attribute to get the browser name; $browserName is private * Dirty attribute to get the browser name; $browserName is private
@ -21,17 +39,22 @@ class WebDriver extends UpstreamDriver
/** /**
* Instantiates the driver. * Instantiates the driver.
* *
* @param string $browser Browser name * @param string $browsername Browser name
* @param array $desiredCapabilities The desired capabilities * @param array $desiredcapabilities The desired capabilities
* @param string $wdHost The WebDriver host * @param string $wdhost The WebDriver host
* @param array $moodleParameters Moodle parameters including our non-behat-friendly selenium capabilities * @param array $moodleparameters Moodle parameters including our non-behat-friendly selenium capabilities
*/ */
public function __construct($browserName = 'chrome', $desiredCapabilities = null, $wdHost = 'http://localhost:4444/wd/hub', $moodleParameters = array()) { public function __construct(
parent::__construct($browserName, $desiredCapabilities, $wdHost); $browsername = 'chrome',
$desiredcapabilities = null,
$wdhost = 'http://localhost:4444/wd/hub',
$moodleparameters = []
) {
parent::__construct($browsername, $desiredcapabilities, $wdhost);
// This class is instantiated by the dependencies injection system so // This class is instantiated by the dependencies injection system so prior to all of beforeSuite subscribers
// prior to all of beforeSuite subscribers which will call getBrowser*() // which will call getBrowser*().
self::$browser = $browserName; self::$browser = $browsername;
} }
/** /**
@ -41,7 +64,6 @@ class WebDriver extends UpstreamDriver
* - To show info about the run. * - To show info about the run.
* - In case there are differences between browsers in the steps. * - In case there are differences between browsers in the steps.
* *
* @static
* @return string * @return string
*/ */
public static function getBrowserName() { public static function getBrowserName() {
@ -51,6 +73,7 @@ class WebDriver extends UpstreamDriver
/** /**
* Post key on specified xpath. * Post key on specified xpath.
* *
* @param string $key
* @param string $xpath * @param string $xpath
*/ */
public function post_key($key, $xpath) { public function post_key($key, $xpath) {

View file

@ -14,37 +14,39 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Driver factory for the Moodle WebDriver.
*
* @package behat
* @copyright 2020 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Driver; namespace Moodle\BehatExtension\Driver;
use Behat\MinkExtension\ServiceContainer\Driver\DriverFactory; use Behat\MinkExtension\ServiceContainer\Driver\DriverFactory;
use OAndreyev\Mink\Driver\WebDriverFactory as UpstreamFactory; use OAndreyev\Mink\Driver\WebDriverFactory as UpstreamFactory;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Definition;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/**
* Driver factory for the Moodle WebDriver.
*
* @package core
* @copyright 2020 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class WebDriverFactory extends UpstreamFactory implements DriverFactory { class WebDriverFactory extends UpstreamFactory implements DriverFactory {
/** /**
* {@inheritdoc} * Builds the service definition for the driver.
*
* @param array $config
* @return Definition
*/ */
public function buildDriver(array $config) public function buildDriver(array $config) {
{ // Merge capabilities.
// Merge capabilities $extracapabilities = $config['capabilities']['extra_capabilities'];
$extraCapabilities = $config['capabilities']['extra_capabilities'];
unset($config['capabilities']['extra_capabilities']); unset($config['capabilities']['extra_capabilities']);
// Ensure that the capabilites.browser is set correctly. // Ensure that the capabilites.browser is set correctly.
$config['capabilities']['browser'] = $config['browser']; $config['capabilities']['browser'] = $config['browser'];
$capabilities = array_replace($this->guessCapabilities(), $extraCapabilities, $config['capabilities']); $capabilities = array_replace($this->guessCapabilities(), $extracapabilities, $config['capabilities']);
// Build driver definition // Build driver definition.
return new Definition(WebDriver::class, [ return new Definition(WebDriver::class, [
$config['browser'], $config['browser'],
$capabilities, $capabilities,
@ -53,10 +55,11 @@ class WebDriverFactory extends UpstreamFactory implements DriverFactory {
} }
/** /**
* {@inheritdoc} * Get the CapabilitiesNode.
*
* @return Node
*/ */
protected function getCapabilitiesNode() protected function getCapabilitiesNode() {
{
$node = parent::getCapabilitiesNode(); $node = parent::getCapabilitiesNode();
// Specify chrome as the default browser. // Specify chrome as the default browser.

View file

@ -14,39 +14,32 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Override step tester to ensure chained steps gets executed.
*
* @package behat
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\EventDispatcher\Tester; namespace Moodle\BehatExtension\EventDispatcher\Tester;
use Behat\Behat\EventDispatcher\Event\AfterStepSetup;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeStepTeardown;
use Behat\Behat\EventDispatcher\Event\BeforeStepTested;
use Behat\Behat\Tester\Result\ExecutedStepResult; use Behat\Behat\Tester\Result\ExecutedStepResult;
use Behat\Behat\Tester\Result\SkippedStepResult; use Behat\Behat\Tester\Result\SkippedStepResult;
use Behat\Behat\Tester\Result\StepResult; use Behat\Behat\Tester\Result\StepResult;
use Behat\Behat\Tester\StepTester;
use Behat\Behat\Tester\Result\UndefinedStepResult; use Behat\Behat\Tester\Result\UndefinedStepResult;
use Moodle\BehatExtension\Context\Step\Given; use Behat\Behat\Tester\StepTester;
use Moodle\BehatExtension\Context\Step\ChainedStep;
use Behat\Gherkin\Node\FeatureNode; use Behat\Gherkin\Node\FeatureNode;
use Behat\Gherkin\Node\StepNode; use Behat\Gherkin\Node\StepNode;
use Behat\Testwork\Call\CallResult; use Behat\Testwork\Call\CallResult;
use Behat\Testwork\Environment\Environment; use Behat\Testwork\Environment\Environment;
use Behat\Testwork\EventDispatcher\TestworkEventDispatcher; use Behat\Testwork\EventDispatcher\TestworkEventDispatcher;
use Behat\Behat\EventDispatcher\Event\AfterStepSetup; use Moodle\BehatExtension\Context\Step\ChainedStep;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeStepTeardown;
use Behat\Behat\EventDispatcher\Event\BeforeStepTested;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Moodle\BehatExtension\Exception\SkippedException; use Moodle\BehatExtension\Exception\SkippedException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Override step tester to ensure chained steps gets executed. * Override step tester to ensure chained steps gets executed.
* *
* @package behat * @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com> * @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
@ -64,7 +57,7 @@ class ChainedStepTester implements StepTester {
/** /**
* @var EventDispatcher keep step event dispatcher. * @var EventDispatcher keep step event dispatcher.
*/ */
private $eventDispatcher; private $eventdispatcher;
/** /**
* Keep status of chained steps if used. * Keep status of chained steps if used.
@ -84,21 +77,34 @@ class ChainedStepTester implements StepTester {
/** /**
* Set event dispatcher to use for events. * Set event dispatcher to use for events.
* *
* @param EventDispatcherInterface $eventDispatcher * @param EventDispatcherInterface $eventdispatcher
*/ */
public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) { public function setEventDispatcher(EventDispatcherInterface $eventdispatcher) {
$this->eventDispatcher = $eventDispatcher; $this->eventdispatcher = $eventdispatcher;
} }
/** /**
* {@inheritdoc} * Sets up step for a test.
*
* @param Environment $env
* @param FeatureNode $feature
* @param StepNode $step
* @param bool $skip
*
* @return Setup
*/ */
public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) { public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) {
return $this->singlesteptester->setUp($env, $feature, $step, $skip); return $this->singlesteptester->setUp($env, $feature, $step, $skip);
} }
/** /**
* {@inheritdoc} * Tests step.
*
* @param Environment $env
* @param FeatureNode $feature
* @param StepNode $step
* @param bool $skip
* @return StepResult
*/ */
public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) { public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) {
$result = $this->singlesteptester->test($env, $feature, $step, $skip); $result = $this->singlesteptester->test($env, $feature, $step, $skip);
@ -123,12 +129,12 @@ class ChainedStepTester implements StepTester {
// Check for exceptions. // Check for exceptions.
// Extra step, looking for a moodle exception, a debugging() message or a PHP debug message. // Extra step, looking for a moodle exception, a debugging() message or a PHP debug message.
$checkingStep = new StepNode('Given', self::EXCEPTIONS_STEP_TEXT, array(), $step->getLine()); $checkingstep = new StepNode('Given', self::EXCEPTIONS_STEP_TEXT, [], $step->getLine());
$afterExceptionCheckingEvent = $this->singlesteptester->test($env, $feature, $checkingStep, $skip); $afterexceptioncheckingevent = $this->singlesteptester->test($env, $feature, $checkingstep, $skip);
$exceptionCheckResult = $this->checkSkipResult($afterExceptionCheckingEvent); $exceptioncheckresult = $this->checkSkipResult($afterexceptioncheckingevent);
if (!$exceptionCheckResult->isPassed()) { if (!$exceptioncheckresult->isPassed()) {
return $exceptionCheckResult; return $exceptioncheckresult;
} }
return $result; return $result;
@ -138,7 +144,14 @@ class ChainedStepTester implements StepTester {
} }
/** /**
* {@inheritdoc} * Tears down step after a test.
*
* @param Environment $env
* @param FeatureNode $feature
* @param StepNode $step
* @param bool $skip
* @param StepResult $result
* @return Teardown
*/ */
public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) { public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) {
return $this->singlesteptester->tearDown($env, $feature, $step, $skip, $result); return $this->singlesteptester->tearDown($env, $feature, $step, $skip, $result);
@ -172,21 +185,20 @@ class ChainedStepTester implements StepTester {
* @param Environment $env * @param Environment $env
* @param FeatureNode $feature * @param FeatureNode $feature
* @param ExecutedStepResult $result * @param ExecutedStepResult $result
* @param $skip * @param bool $skip
*
* @return ExecutedStepResult|StepResult * @return ExecutedStepResult|StepResult
*/ */
private function runChainedSteps(Environment $env, FeatureNode $feature, ExecutedStepResult $result, $skip) { private function runChainedSteps(Environment $env, FeatureNode $feature, ExecutedStepResult $result, $skip) {
// Set chained setp is used, so it can be used by formatter to o/p. // Set chained setp is used, so it can be used by formatter to o/p.
self::$chainedstepused = true; self::$chainedstepused = true;
$callResult = $result->getCallResult(); $callresult = $result->getCallResult();
$steps = $callResult->getReturn(); $steps = $callresult->getReturn();
if (!is_array($steps)) { if (!is_array($steps)) {
// Test it, no need to dispatch events for single chain. // Test it, no need to dispatch events for single chain.
$stepResult = $this->test($env, $feature, $steps, $skip); $stepresult = $this->test($env, $feature, $steps, $skip);
return $this->checkSkipResult($stepResult); return $this->checkSkipResult($stepresult);
} }
// Test all steps. // Test all steps.
@ -195,10 +207,10 @@ class ChainedStepTester implements StepTester {
$event = new BeforeStepTested($env, $feature, $step); $event = new BeforeStepTested($env, $feature, $step);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::BEFORE); $this->eventdispatcher->dispatch($event, $event::BEFORE);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::BEFORE, $event); $this->eventdispatcher->dispatch($event::BEFORE, $event);
} }
$setup = $this->setUp($env, $feature, $step, $skip); $setup = $this->setUp($env, $feature, $step, $skip);
@ -206,23 +218,23 @@ class ChainedStepTester implements StepTester {
$event = new AfterStepSetup($env, $feature, $step, $setup); $event = new AfterStepSetup($env, $feature, $step, $setup);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::AFTER_SETUP); $this->eventdispatcher->dispatch($event, $event::AFTER_SETUP);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); $this->eventdispatcher->dispatch($event::AFTER_SETUP, $event);
} }
// Test it. // Test it.
$stepResult = $this->test($env, $feature, $step, $skip); $stepresult = $this->test($env, $feature, $step, $skip);
// Tear down. // Tear down.
$event = new BeforeStepTeardown($env, $feature, $step, $result); $event = new BeforeStepTeardown($env, $feature, $step, $result);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::BEFORE_TEARDOWN); $this->eventdispatcher->dispatch($event, $event::BEFORE_TEARDOWN);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); $this->eventdispatcher->dispatch($event::BEFORE_TEARDOWN, $event);
} }
$teardown = $this->tearDown($env, $feature, $step, $skip, $result); $teardown = $this->tearDown($env, $feature, $step, $skip, $result);
@ -230,18 +242,17 @@ class ChainedStepTester implements StepTester {
$event = new AfterStepTested($env, $feature, $step, $result, $teardown); $event = new AfterStepTested($env, $feature, $step, $result, $teardown);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::AFTER); $this->eventdispatcher->dispatch($event, $event::AFTER);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::AFTER, $event); $this->eventdispatcher->dispatch($event::AFTER, $event);
} }
// if (!$stepresult->isPassed()) {
if (!$stepResult->isPassed()) { return $this->checkSkipResult($stepresult);
return $this->checkSkipResult($stepResult);
} }
} }
return $this->checkSkipResult($stepResult); return $this->checkSkipResult($stepresult);
} }
/** /**

View file

@ -1,5 +1,4 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
@ -15,16 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Override step tester to ensure chained steps gets executed.
*
* @package behat
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\EventDispatcher\Tester; namespace Moodle\BehatExtension\EventDispatcher\Tester;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
use Behat\Behat\EventDispatcher\Event\AfterStepSetup; use Behat\Behat\EventDispatcher\Event\AfterStepSetup;
use Behat\Behat\EventDispatcher\Event\AfterStepTested; use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeStepTeardown; use Behat\Behat\EventDispatcher\Event\BeforeStepTeardown;
@ -40,89 +33,106 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* Step tester dispatching BEFORE/AFTER events during tests. * Step tester dispatching BEFORE/AFTER events during tests.
* *
* @package behat * @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com> * @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class MoodleEventDispatchingStepTester implements StepTester final class MoodleEventDispatchingStepTester implements StepTester {
{
/** /** @var StepTester */
* @var StepTester private $basetester;
*/
private $baseTester; /** @var EventDispatcherInterface */
/** private $eventdispatcher;
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/** /**
* Initializes tester. * Initializes tester.
* *
* @param StepTester $baseTester * @param StepTester $basetester
* @param EventDispatcherInterface $eventDispatcher * @param EventDispatcherInterface $eventdispatcher
*/ */
public function __construct(StepTester $baseTester, EventDispatcherInterface $eventDispatcher) { public function __construct(StepTester $basetester, EventDispatcherInterface $eventdispatcher) {
$this->baseTester = $baseTester; $this->basetester = $basetester;
$this->eventDispatcher = $eventDispatcher; $this->eventdispatcher = $eventdispatcher;
} }
/** /**
* {@inheritdoc} * Sets up step for a test.
*
* @param Environment $env
* @param FeatureNode $feature
* @param StepNode $step
* @param bool $skip
*
* @return Setup
*/ */
public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) { public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) {
$event = new BeforeStepTested($env, $feature, $step); $event = new BeforeStepTested($env, $feature, $step);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::BEFORE); $this->eventdispatcher->dispatch($event, $event::BEFORE);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::BEFORE, $event); $this->eventdispatcher->dispatch($event::BEFORE, $event);
} }
$setup = $this->baseTester->setUp($env, $feature, $step, $skip); $setup = $this->basetester->setUp($env, $feature, $step, $skip);
$this->baseTester->setEventDispatcher($this->eventDispatcher); $this->basetester->setEventDispatcher($this->eventdispatcher);
$event = new AfterStepSetup($env, $feature, $step, $setup); $event = new AfterStepSetup($env, $feature, $step, $setup);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::AFTER_SETUP); $this->eventdispatcher->dispatch($event, $event::AFTER_SETUP);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); $this->eventdispatcher->dispatch($event::AFTER_SETUP, $event);
} }
return $setup; return $setup;
} }
/** /**
* {@inheritdoc} * Tests step.
*
* @param Environment $env
* @param FeatureNode $feature
* @param StepNode $step
* @param bool $skip
* @return StepResult
*/ */
public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) { public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) {
return $this->baseTester->test($env, $feature, $step, $skip); return $this->basetester->test($env, $feature, $step, $skip);
} }
/** /**
* {@inheritdoc} * Tears down step after a test.
*
* @param Environment $env
* @param FeatureNode $feature
* @param StepNode $step
* @param bool $skip
* @param StepResult $result
* @return Teardown
*/ */
public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) { public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) {
$event = new BeforeStepTeardown($env, $feature, $step, $result); $event = new BeforeStepTeardown($env, $feature, $step, $result);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::BEFORE_TEARDOWN); $this->eventdispatcher->dispatch($event, $event::BEFORE_TEARDOWN);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); $this->eventdispatcher->dispatch($event::BEFORE_TEARDOWN, $event);
} }
$teardown = $this->baseTester->tearDown($env, $feature, $step, $skip, $result); $teardown = $this->basetester->tearDown($env, $feature, $step, $skip, $result);
$event = new AfterStepTested($env, $feature, $step, $result, $teardown); $event = new AfterStepTested($env, $feature, $step, $result, $teardown);
if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) { if (TestworkEventDispatcher::DISPATCHER_VERSION === 2) {
// Symfony 4.3 and up. // Symfony 4.3 and up.
$this->eventDispatcher->dispatch($event, $event::AFTER); $this->eventdispatcher->dispatch($event, $event::AFTER);
} else { } else {
// TODO: Remove when our min supported version is >= 4.3. // TODO: Remove when our min supported version is >= 4.3.
$this->eventDispatcher->dispatch($event::AFTER, $event); $this->eventdispatcher->dispatch($event::AFTER, $event);
} }
return $teardown; return $teardown;

View file

@ -1,10 +1,26 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Exception; namespace Moodle\BehatExtension\Exception;
/** /**
* Skipped exception (throw this to mark step as "skipped"). * Skipped exception (throw this to mark step as "skipped").
* *
* @package core
* @author Jerome Mouneyrac * @author Jerome Mouneyrac
*/ */
class SkippedException extends \Exception{} class SkippedException extends \Exception {
}

View file

@ -14,13 +14,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Skips gherkin features using a file with the list of scenarios.
*
* @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Locator; namespace Moodle\BehatExtension\Locator;
use Behat\Behat\Gherkin\Specification\LazyFeatureIterator; use Behat\Behat\Gherkin\Specification\LazyFeatureIterator;
@ -29,10 +22,14 @@ use Behat\Testwork\Specification\Locator\SpecificationLocator;
use Behat\Testwork\Specification\NoSpecificationsIterator; use Behat\Testwork\Specification\NoSpecificationsIterator;
use Behat\Testwork\Suite\Suite; use Behat\Testwork\Suite\Suite;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Skips gherkin features using a file with the list of scenarios. * Skips gherkin features using a file with the list of scenarios.
* *
* @package core
* @copyright 2016 onwards Rajesh Taneja * @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class FilesystemSkipPassedListLocator implements SpecificationLocator { final class FilesystemSkipPassedListLocator implements SpecificationLocator {
/** /**
@ -50,14 +47,21 @@ final class FilesystemSkipPassedListLocator implements SpecificationLocator {
} }
/** /**
* {@inheritdoc} * Returns array of strings representing examples of supported specification locators.
*
* @return string[]
*/ */
public function getLocatorExamples() { public function getLocatorExamples() {
return array(); return [];
} }
/** /**
* {@inheritdoc} * Locates specifications and wraps them into iterator.
*
* @param Suite $suite
* @param string $locator
*
* @return SpecificationIterator
*/ */
public function locateSpecifications(Suite $suite, $locator) { public function locateSpecifications(Suite $suite, $locator) {
if (!is_file($locator) || 'passed' !== pathinfo($locator, PATHINFO_EXTENSION)) { if (!is_file($locator) || 'passed' !== pathinfo($locator, PATHINFO_EXTENSION)) {
@ -88,7 +92,8 @@ final class FilesystemSkipPassedListLocator implements SpecificationLocator {
private function getSuitePaths(Suite $suite) { private function getSuitePaths(Suite $suite) {
if (!is_array($suite->getSetting('paths'))) { if (!is_array($suite->getSetting('paths'))) {
throw new SuiteConfigurationException( throw new SuiteConfigurationException(
sprintf('`paths` setting of the "%s" suite is expected to be an array, %s given.', sprintf(
'"paths" setting of the "%s" suite is expected to be an array, %s given.',
$suite->getName(), $suite->getName(),
gettype($suite->getSetting('paths')) gettype($suite->getSetting('paths'))
), ),

View file

@ -14,53 +14,37 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Behat\EventDispatcher\Event\AfterOutlineTested;
use Behat\Behat\EventDispatcher\Event\AfterScenarioTested;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Feature step counter for distributing features between parallel runs. * Feature step counter for distributing features between parallel runs.
* *
* Use it with --dry-run (and any other selectors combination) to * Use it with --dry-run (and any other selectors combination) to
* get the results quickly. * get the results quickly.
* *
* @package core
* @copyright 2015 onwards Rajesh Taneja * @copyright 2015 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Behat\EventDispatcher\Event\AfterFeatureTested;
use Behat\Behat\EventDispatcher\Event\AfterOutlineTested;
use Behat\Behat\EventDispatcher\Event\AfterScenarioTested;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested;
use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested;
use Behat\Behat\EventDispatcher\Event\BeforeScenarioTested;
use Behat\Behat\Tester\Result\ExecutedStepResult;
use Behat\Testwork\Counter\Memory;
use Behat\Testwork\Counter\Timer;
use Behat\Testwork\EventDispatcher\Event\AfterExerciseCompleted;
use Behat\Testwork\EventDispatcher\Event\AfterSuiteTested;
use Behat\Testwork\EventDispatcher\Event\BeforeExerciseCompleted;
use Behat\Testwork\EventDispatcher\Event\BeforeSuiteTested;
use Behat\Testwork\Output\Exception\BadOutputPathException;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter;
class MoodleListFormatter implements Formatter { class MoodleListFormatter implements Formatter {
/** /** @var OutputPrinter */
* @var OutputPrinter
*/
private $printer; private $printer;
/**
* @var array /** @var array */
*/
private $parameters; private $parameters;
/**
* @var string /** @var string */
*/
private $name; private $name;
/**
* @var string /** @var string */
*/
private $description; private $description;
/** /**
@ -80,46 +64,60 @@ class MoodleListFormatter implements Formatter {
/** /**
* Returns an array of event names this subscriber wants to listen to. * Returns an array of event names this subscriber wants to listen to.
*
* @return array The event names to listen to * @return array The event names to listen to
*/ */
public static function getSubscribedEvents() { public static function getSubscribedEvents() {
return array( return [
'tester.scenario_tested.after' => 'afterScenario', 'tester.scenario_tested.after' => 'afterScenario',
'tester.outline_tested.after' => 'afterOutlineExample', 'tester.outline_tested.after' => 'afterOutlineExample',
); ];
} }
/** /**
* {@inheritdoc} * Returns formatter name.
*
* @return string
*/ */
public function getName() { public function getName() {
return $this->name; return $this->name;
} }
/** /**
* {@inheritdoc} * Returns formatter description.
*
* @return string
*/ */
public function getDescription() { public function getDescription() {
return $this->description; return $this->description;
} }
/** /**
* {@inheritdoc} * Returns formatter output printer.
*
* @return OutputPrinter
*/ */
public function getOutputPrinter() { public function getOutputPrinter() {
return $this->printer; return $this->printer;
} }
/** /**
* {@inheritdoc} * Sets formatter parameter.
*
* @param string $name
* @param mixed $value
*/ */
public function setParameter($name, $value) { public function setParameter($name, $value) {
$this->parameters[$name] = $value; $this->parameters[$name] = $value;
} }
/** /**
* {@inheritdoc} * Returns parameter name.
*
* @param string $name
*
* @return mixed
*/ */
public function getParameter($name) { public function getParameter($name) {
return isset($this->parameters[$name]) ? $this->parameters[$name] : null; return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
@ -128,7 +126,7 @@ class MoodleListFormatter implements Formatter {
/** /**
* Listens to "scenario.after" event. * Listens to "scenario.after" event.
* *
* @param ScenarioEvent $event * @param AfterScenarioTested $event
*/ */
public function afterScenario(AfterScenarioTested $event) { public function afterScenario(AfterScenarioTested $event) {
$scenario = $event->getScenario(); $scenario = $event->getScenario();
@ -139,7 +137,7 @@ class MoodleListFormatter implements Formatter {
/** /**
* Listens to "outline.example.after" event. * Listens to "outline.example.after" event.
* *
* @param OutlineExampleEvent $event * @param AfterOutlineTested $event
*/ */
public function afterOutlineExample(AfterOutlineTested $event) { public function afterOutlineExample(AfterOutlineTested $event) {
$outline = $event->getOutline(); $outline = $event->getOutline();

View file

@ -1,5 +1,4 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
@ -15,42 +14,37 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Moodle behat context class resolver.
*
* @package behat
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Output\Formatter; namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension; use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension;
use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory;
use Behat\Testwork\Output\ServiceContainer\OutputExtension; use Behat\Testwork\Output\ServiceContainer\OutputExtension;
use Behat\Testwork\ServiceContainer\ServiceProcessor; use Behat\Testwork\ServiceContainer\ServiceProcessor;
use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Reference;
use Behat\Behat\Output\ServiceContainer\Formatter\ProgressFormatterFactory;
use Behat\Behat\EventDispatcher\Event\OutlineTested;
use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory;
use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension;
class MoodleProgressFormatterFactory implements FormatterFactory { // phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/**
* @var ServiceProcessor /**
* Moodle behat context class resolver.
*
* @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class MoodleProgressFormatterFactory implements FormatterFactory {
/** @var ServiceProcessor */
private $processor; private $processor;
/* /** @var string moodle progress ID */
* Available services
*/
const ROOT_LISTENER_ID_MOODLE = 'output.node.listener.moodleprogress'; const ROOT_LISTENER_ID_MOODLE = 'output.node.listener.moodleprogress';
/** @var string moodle printer ID */
const RESULT_TO_STRING_CONVERTER_ID_MOODLE = 'output.node.printer.result_to_string'; const RESULT_TO_STRING_CONVERTER_ID_MOODLE = 'output.node.printer.result_to_string';
/* /** @var string Available extension points */
* Available extension points
*/
const ROOT_LISTENER_WRAPPER_TAG_MOODLE = 'output.node.listener.moodleprogress.wrapper'; const ROOT_LISTENER_WRAPPER_TAG_MOODLE = 'output.node.listener.moodleprogress.wrapper';
/** /**
@ -63,7 +57,9 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
} }
/** /**
* {@inheritdoc} * Builds formatter configuration.
*
* @param ContainerBuilder $container
*/ */
public function buildFormatter(ContainerBuilder $container) { public function buildFormatter(ContainerBuilder $container) {
$this->loadRootNodeListener($container); $this->loadRootNodeListener($container);
@ -73,7 +69,9 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
} }
/** /**
* {@inheritdoc} * Processes formatter configuration.
*
* @param ContainerBuilder $container
*/ */
public function processFormatter(ContainerBuilder $container) { public function processFormatter(ContainerBuilder $container) {
$this->processListenerWrappers($container); $this->processListenerWrappers($container);
@ -85,9 +83,9 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function loadRootNodeListener(ContainerBuilder $container) { protected function loadRootNodeListener(ContainerBuilder $container) {
$definition = new Definition('Behat\Behat\Output\Node\EventListener\AST\StepListener', array( $definition = new Definition('Behat\Behat\Output\Node\EventListener\AST\StepListener', [
new Reference('output.node.printer.moodleprogress.step') new Reference('output.node.printer.moodleprogress.step')
)); ]);
$container->setDefinition(self::ROOT_LISTENER_ID_MOODLE, $definition); $container->setDefinition(self::ROOT_LISTENER_ID_MOODLE, $definition);
} }
@ -103,43 +101,44 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
$moodleconfig = $container->getParameter('behat.moodle.parameters'); $moodleconfig = $container->getParameter('behat.moodle.parameters');
$definition = new Definition('Moodle\BehatExtension\Output\Printer\MoodleProgressPrinter', $definition = new Definition(
array($moodleconfig['moodledirroot'])); 'Moodle\BehatExtension\Output\Printer\MoodleProgressPrinter',
[$moodleconfig['moodledirroot']]
);
$container->setDefinition('moodle.output.node.printer.moodleprogress.printer', $definition); $container->setDefinition('moodle.output.node.printer.moodleprogress.printer', $definition);
$definition = new Definition('Behat\Testwork\Output\NodeEventListeningFormatter', array( $definition = new Definition('Behat\Testwork\Output\NodeEventListeningFormatter', [
'moodle_progress', 'moodle_progress',
'Prints information about then run followed by one character per step.', 'Prints information about then run followed by one character per step.',
array( [
'timer' => true 'timer' => true
), ],
$this->createOutputPrinterDefinition(), $this->createOutputPrinterDefinition(),
new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', array( new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', [
array( [
new Reference(self::ROOT_LISTENER_ID_MOODLE), new Reference(self::ROOT_LISTENER_ID_MOODLE),
new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StatisticsListener', array( new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StatisticsListener', [
new Reference('output.moodleprogress.statistics'), new Reference('output.moodleprogress.statistics'),
new Reference('output.node.printer.moodleprogress.statistics') new Reference('output.node.printer.moodleprogress.statistics')
)), ]),
new Definition('Behat\Behat\Output\Node\EventListener\Statistics\ScenarioStatsListener', array( new Definition('Behat\Behat\Output\Node\EventListener\Statistics\ScenarioStatsListener', [
new Reference('output.moodleprogress.statistics') new Reference('output.moodleprogress.statistics')
)), ]),
new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StepStatsListener', array( new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StepStatsListener', [
new Reference('output.moodleprogress.statistics'), new Reference('output.moodleprogress.statistics'),
new Reference(ExceptionExtension::PRESENTER_ID) new Reference(ExceptionExtension::PRESENTER_ID)
)), ]),
new Definition('Behat\Behat\Output\Node\EventListener\Statistics\HookStatsListener', array( new Definition('Behat\Behat\Output\Node\EventListener\Statistics\HookStatsListener', [
new Reference('output.moodleprogress.statistics'), new Reference('output.moodleprogress.statistics'),
new Reference(ExceptionExtension::PRESENTER_ID) new Reference(ExceptionExtension::PRESENTER_ID)
)), ]),
new Definition('Behat\Behat\Output\Node\EventListener\AST\SuiteListener', array( new Definition('Behat\Behat\Output\Node\EventListener\AST\SuiteListener', [
new Reference('moodle.output.node.printer.moodleprogress.printer') new Reference('moodle.output.node.printer.moodleprogress.printer')
)) ])
) ]
) ])
) ]);
)); $definition->addTag(OutputExtension::FORMATTER_TAG, ['priority' => 1]);
$definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 1));
$container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodleprogress', $definition); $container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodleprogress', $definition);
} }
@ -159,29 +158,29 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function loadCorePrinters(ContainerBuilder $container) { protected function loadCorePrinters(ContainerBuilder $container) {
$definition = new Definition('Behat\Behat\Output\Node\Printer\CounterPrinter', array( $definition = new Definition('Behat\Behat\Output\Node\Printer\CounterPrinter', [
new Reference(self::RESULT_TO_STRING_CONVERTER_ID_MOODLE), new Reference(self::RESULT_TO_STRING_CONVERTER_ID_MOODLE),
new Reference(TranslatorExtension::TRANSLATOR_ID), new Reference(TranslatorExtension::TRANSLATOR_ID),
)); ]);
$container->setDefinition('output.node.moodle.printer.counter', $definition); $container->setDefinition('output.node.moodle.printer.counter', $definition);
$definition = new Definition('Behat\Behat\Output\Node\Printer\ListPrinter', array( $definition = new Definition('Behat\Behat\Output\Node\Printer\ListPrinter', [
new Reference(self::RESULT_TO_STRING_CONVERTER_ID_MOODLE), new Reference(self::RESULT_TO_STRING_CONVERTER_ID_MOODLE),
new Reference(ExceptionExtension::PRESENTER_ID), new Reference(ExceptionExtension::PRESENTER_ID),
new Reference(TranslatorExtension::TRANSLATOR_ID), new Reference(TranslatorExtension::TRANSLATOR_ID),
'%paths.base%' '%paths.base%'
)); ]);
$container->setDefinition('output.node.moodle.printer.list', $definition); $container->setDefinition('output.node.moodle.printer.list', $definition);
$definition = new Definition('Behat\Behat\Output\Node\Printer\Progress\ProgressStepPrinter', array( $definition = new Definition('Behat\Behat\Output\Node\Printer\Progress\ProgressStepPrinter', [
new Reference(self::RESULT_TO_STRING_CONVERTER_ID_MOODLE) new Reference(self::RESULT_TO_STRING_CONVERTER_ID_MOODLE)
)); ]);
$container->setDefinition('output.node.printer.moodleprogress.step', $definition); $container->setDefinition('output.node.printer.moodleprogress.step', $definition);
$definition = new Definition('Behat\Behat\Output\Node\Printer\Progress\ProgressStatisticsPrinter', array( $definition = new Definition('Behat\Behat\Output\Node\Printer\Progress\ProgressStatisticsPrinter', [
new Reference('output.node.moodle.printer.counter'), new Reference('output.node.moodle.printer.counter'),
new Reference('output.node.moodle.printer.list') new Reference('output.node.moodle.printer.list')
)); ]);
$container->setDefinition('output.node.printer.moodleprogress.statistics', $definition); $container->setDefinition('output.node.printer.moodleprogress.statistics', $definition);
} }
@ -191,9 +190,9 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
* @return Definition * @return Definition
*/ */
protected function createOutputPrinterDefinition() { protected function createOutputPrinterDefinition() {
return new Definition('Behat\Testwork\Output\Printer\StreamOutputPrinter', array( return new Definition('Behat\Testwork\Output\Printer\StreamOutputPrinter', [
new Definition('Behat\Behat\Output\Printer\ConsoleOutputFactory'), new Definition('Behat\Behat\Output\Printer\ConsoleOutputFactory'),
)); ]);
} }
/** /**
@ -202,6 +201,10 @@ class MoodleProgressFormatterFactory implements FormatterFactory {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function processListenerWrappers(ContainerBuilder $container) { protected function processListenerWrappers(ContainerBuilder $container) {
$this->processor->processWrapperServices($container, self::ROOT_LISTENER_ID_MOODLE, self::ROOT_LISTENER_WRAPPER_TAG_MOODLE); $this->processor->processWrapperServices(
$container,
self::ROOT_LISTENER_ID_MOODLE,
self::ROOT_LISTENER_WRAPPER_TAG_MOODLE
);
} }
} }

View file

@ -14,64 +14,45 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeScenarioTested;
use Behat\Behat\EventDispatcher\Event\BeforeStepTested;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Feature step counter for distributing features between parallel runs. * Feature step counter for distributing features between parallel runs.
* *
* Use it with --dry-run (and any other selectors combination) to * Use it with --dry-run (and any other selectors combination) to
* get the results quickly. * get the results quickly.
* *
* @package core
* @copyright 2016 onwards Rajesh Taneja * @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Behat\EventDispatcher\Event\AfterFeatureTested;
use Behat\Behat\EventDispatcher\Event\AfterOutlineTested;
use Behat\Behat\EventDispatcher\Event\AfterScenarioTested;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested;
use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested;
use Behat\Behat\EventDispatcher\Event\BeforeScenarioTested;
use Behat\Behat\EventDispatcher\Event\BeforeStepTested;
use Behat\Behat\Tester\Result\ExecutedStepResult;
use Behat\Testwork\Counter\Memory;
use Behat\Testwork\Counter\Timer;
use Behat\Testwork\EventDispatcher\Event\AfterExerciseCompleted;
use Behat\Testwork\EventDispatcher\Event\AfterSuiteTested;
use Behat\Testwork\EventDispatcher\Event\BeforeExerciseCompleted;
use Behat\Testwork\EventDispatcher\Event\BeforeSuiteTested;
use Behat\Testwork\Output\Exception\BadOutputPathException;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter;
class MoodleScreenshotFormatter implements Formatter { class MoodleScreenshotFormatter implements Formatter {
/** /** @var OutputPrinter */
* @var OutputPrinter
*/
private $printer; private $printer;
/**
* @var array /** @var array */
*/
private $parameters; private $parameters;
/**
* @var string /** @var string */
*/
private $name; private $name;
/**
* @var string /** @var string */
*/
private $description; private $description;
/** /** @var int The scenario count */
* @var int The scenario count.
*/
protected static $currentscenariocount = 0; protected static $currentscenariocount = 0;
/** /** @var int The step count within the current scenario */
* @var int The step count within the current scenario.
*/
protected static $currentscenariostepcount = 0; protected static $currentscenariostepcount = 0;
/** /**
@ -88,7 +69,6 @@ class MoodleScreenshotFormatter implements Formatter {
* @param string $description * @param string $description
* @param array $parameters * @param array $parameters
* @param OutputPrinter $printer * @param OutputPrinter $printer
* @param EventListener $listener
*/ */
public function __construct($name, $description, array $parameters, OutputPrinter $printer) { public function __construct($name, $description, array $parameters, OutputPrinter $printer) {
$this->name = $name; $this->name = $name;
@ -99,47 +79,59 @@ class MoodleScreenshotFormatter implements Formatter {
/** /**
* Returns an array of event names this subscriber wants to listen to. * Returns an array of event names this subscriber wants to listen to.
*
* @return array The event names to listen to * @return array The event names to listen to
*/ */
public static function getSubscribedEvents() { public static function getSubscribedEvents() {
return array( return [
'tester.scenario_tested.before' => 'beforeScenario', 'tester.scenario_tested.before' => 'beforeScenario',
'tester.step_tested.before' => 'beforeStep', 'tester.step_tested.before' => 'beforeStep',
'tester.step_tested.after' => 'afterStep', 'tester.step_tested.after' => 'afterStep',
); ];
} }
/** /**
* {@inheritdoc} * Returns formatter name.
*
* @return string
*/ */
public function getName() { public function getName() {
return $this->name; return $this->name;
} }
/** /**
* {@inheritdoc} * Returns formatter description.
*
* @return string
*/ */
public function getDescription() { public function getDescription() {
return $this->description; return $this->description;
} }
/** /**
* {@inheritdoc} * Returns formatter output printer.
*
* @return OutputPrinter
*/ */
public function getOutputPrinter() { public function getOutputPrinter() {
return $this->printer; return $this->printer;
} }
/** /**
* {@inheritdoc} * Sets formatter parameter.
*
* @param string $name
* @param mixed $value
*/ */
public function setParameter($name, $value) { public function setParameter($name, $value) {
$this->parameters[$name] = $value; $this->parameters[$name] = $value;
} }
/** /**
* {@inheritdoc} * Returns parameter name.
*
* @param string $name
* @return mixed
*/ */
public function getParameter($name) { public function getParameter($name) {
return isset($this->parameters[$name]) ? $this->parameters[$name] : null; return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
@ -221,7 +213,8 @@ class MoodleScreenshotFormatter implements Formatter {
if (!is_dir(self::$faildumpdirname) && !mkdir(self::$faildumpdirname, $dirpermissions, true)) { if (!is_dir(self::$faildumpdirname) && !mkdir(self::$faildumpdirname, $dirpermissions, true)) {
// It shouldn't, we already checked that the directory is writable. // It shouldn't, we already checked that the directory is writable.
throw new FormatterException(sprintf( throw new FormatterException(sprintf(
'No directories can be created inside %s, check the directory permissions.', $screenshotpath)); 'No directories can be created inside %s, check the directory permissions.', $screenshotpath
));
} }
return self::$faildumpdirname; return self::$faildumpdirname;
@ -232,6 +225,7 @@ class MoodleScreenshotFormatter implements Formatter {
* *
* @throws Exception * @throws Exception
* @param AfterStepTested $event * @param AfterStepTested $event
* @param Context $context
*/ */
protected function take_screenshot(AfterStepTested $event, $context) { protected function take_screenshot(AfterStepTested $event, $context) {
// Goutte can't save screenshots. // Goutte can't save screenshots.
@ -249,6 +243,7 @@ class MoodleScreenshotFormatter implements Formatter {
* *
* @throws Exception * @throws Exception
* @param AfterStepTested $event * @param AfterStepTested $event
* @param \Behat\Context\Context\Context $context
*/ */
protected function take_contentdump(AfterStepTested $event, $context) { protected function take_contentdump(AfterStepTested $event, $context) {
list ($dir, $filename) = $this->get_faildump_filename($event, 'html'); list ($dir, $filename) = $this->get_faildump_filename($event, 'html');
@ -282,7 +277,8 @@ class MoodleScreenshotFormatter implements Formatter {
if (!is_dir($dir) && !mkdir($dir, $dirpermissions, true)) { if (!is_dir($dir) && !mkdir($dir, $dirpermissions, true)) {
// We already checked that the directory is writable. This should not fail. // We already checked that the directory is writable. This should not fail.
throw new FormatterException(sprintf( throw new FormatterException(sprintf(
'No directories can be created inside %s, check the directory permissions.', $dir)); 'No directories can be created inside %s, check the directory permissions.', $dir
));
} }
// The failed step text. // The failed step text.
@ -294,6 +290,6 @@ class MoodleScreenshotFormatter implements Formatter {
// File name limited to 255 characters. Leaving 4 chars for the file // File name limited to 255 characters. Leaving 4 chars for the file
// extension as we allow .png for images and .html for DOM contents. // extension as we allow .png for images and .html for DOM contents.
$filename = substr($filename, 0, 250) . '.' . $filetype; $filename = substr($filename, 0, 250) . '.' . $filetype;
return array($dir, $filename); return [$dir, $filename];
} }
} }

View file

@ -14,56 +14,41 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Behat\EventDispatcher\Event\AfterFeatureTested;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Feature step counter for distributing features between parallel runs. * Feature step counter for distributing features between parallel runs.
* *
* Use it with --dry-run (and any other selectors combination) to * Use it with --dry-run (and any other selectors combination) to
* get the results quickly. * get the results quickly.
* *
* @package core
* @copyright 2016 onwards Rajesh Taneja * @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace Moodle\BehatExtension\Output\Formatter;
use Behat\Behat\EventDispatcher\Event\AfterFeatureTested;
use Behat\Behat\EventDispatcher\Event\AfterOutlineTested;
use Behat\Behat\EventDispatcher\Event\AfterScenarioTested;
use Behat\Behat\EventDispatcher\Event\AfterStepTested;
use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested;
use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested;
use Behat\Behat\EventDispatcher\Event\BeforeScenarioTested;
use Behat\Behat\Tester\Result\ExecutedStepResult;
use Behat\Testwork\Counter\Memory;
use Behat\Testwork\Counter\Timer;
use Behat\Testwork\EventDispatcher\Event\AfterExerciseCompleted;
use Behat\Testwork\EventDispatcher\Event\AfterSuiteTested;
use Behat\Testwork\EventDispatcher\Event\BeforeExerciseCompleted;
use Behat\Testwork\EventDispatcher\Event\BeforeSuiteTested;
use Behat\Testwork\Output\Exception\BadOutputPathException;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter;
class MoodleStepcountFormatter implements Formatter { class MoodleStepcountFormatter implements Formatter {
/** @var int Number of steps executed in feature file. */ /** @var int Number of steps executed in feature file. */
private static $stepcount = 0; private static $stepcount = 0;
/** /** @var OutputPrinter */
* @var OutputPrinter
*/
private $printer; private $printer;
/**
* @var array /** @var array */
*/
private $parameters; private $parameters;
/**
* @var string /** @var string */
*/
private $name; private $name;
/**
* @var string /** @var string */
*/
private $description; private $description;
/** /**
@ -73,7 +58,6 @@ class MoodleStepcountFormatter implements Formatter {
* @param string $description * @param string $description
* @param array $parameters * @param array $parameters
* @param OutputPrinter $printer * @param OutputPrinter $printer
* @param EventListener $listener
*/ */
public function __construct($name, $description, array $parameters, OutputPrinter $printer) { public function __construct($name, $description, array $parameters, OutputPrinter $printer) {
$this->name = $name; $this->name = $name;
@ -84,47 +68,59 @@ class MoodleStepcountFormatter implements Formatter {
/** /**
* Returns an array of event names this subscriber wants to listen to. * Returns an array of event names this subscriber wants to listen to.
*
* @return array The event names to listen to * @return array The event names to listen to
*/ */
public static function getSubscribedEvents() { public static function getSubscribedEvents() {
return array( return [
'tester.feature_tested.before' => 'beforeFeature', 'tester.feature_tested.before' => 'beforeFeature',
'tester.feature_tested.after' => 'afterFeature', 'tester.feature_tested.after' => 'afterFeature',
'tester.step_tested.after' => 'afterStep', 'tester.step_tested.after' => 'afterStep',
); ];
} }
/** /**
* {@inheritdoc} * Returns formatter name.
*
* @return string
*/ */
public function getName() { public function getName() {
return $this->name; return $this->name;
} }
/** /**
* {@inheritdoc} * Returns formatter description.
*
* @return string
*/ */
public function getDescription() { public function getDescription() {
return $this->description; return $this->description;
} }
/** /**
* {@inheritdoc} * Returns formatter output printer.
*
* @return OutputPrinter
*/ */
public function getOutputPrinter() { public function getOutputPrinter() {
return $this->printer; return $this->printer;
} }
/** /**
* {@inheritdoc} * Sets formatter parameter.
*
* @param string $name
* @param mixed $value
*/ */
public function setParameter($name, $value) { public function setParameter($name, $value) {
$this->parameters[$name] = $value; $this->parameters[$name] = $value;
} }
/** /**
* {@inheritdoc} * Returns parameter name.
*
* @param string $name
* @return mixed
*/ */
public function getParameter($name) { public function getParameter($name) {
return isset($this->parameters[$name]) ? $this->parameters[$name] : null; return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
@ -133,7 +129,7 @@ class MoodleStepcountFormatter implements Formatter {
/** /**
* Listens to "feature.before" event. * Listens to "feature.before" event.
* *
* @param FeatureEvent $event * @param BeforeFeatureTested $event
*/ */
public function beforeFeature(BeforeFeatureTested $event) { public function beforeFeature(BeforeFeatureTested $event) {
self::$stepcount = 0; self::$stepcount = 0;
@ -142,7 +138,7 @@ class MoodleStepcountFormatter implements Formatter {
/** /**
* Listens to "feature.after" event. * Listens to "feature.after" event.
* *
* @param FeatureEvent $event * @param AfterFeatureTested $event
*/ */
public function afterFeature(AfterFeatureTested $event) { public function afterFeature(AfterFeatureTested $event) {
$this->printer->writeln($event->getFeature()->getFile() . '::' . self::$stepcount); $this->printer->writeln($event->getFeature()->getFile() . '::' . self::$stepcount);
@ -151,7 +147,7 @@ class MoodleStepcountFormatter implements Formatter {
/** /**
* Listens to "step.after" event. * Listens to "step.after" event.
* *
* @param StepEvent $event * @param AfterStepTested $event
*/ */
public function afterStep(AfterStepTested $event) { public function afterStep(AfterStepTested $event) {
self::$stepcount++; self::$stepcount++;

View file

@ -1,5 +1,4 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/ // This file is part of Moodle - http://moodle.org/
// //
// Moodle is free software: you can redistribute it and/or modify // Moodle is free software: you can redistribute it and/or modify
@ -15,28 +14,25 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Moodle behat context class resolver.
*
* @package behat
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Output\Printer; namespace Moodle\BehatExtension\Output\Printer;
use Behat\Behat\Output\Node\Printer\SetupPrinter; use Behat\Behat\Output\Node\Printer\SetupPrinter;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Tester\Setup\Setup;
use Behat\Testwork\Tester\Setup\Teardown;
use Behat\Testwork\Call\CallResult; use Behat\Testwork\Call\CallResult;
use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; use Behat\Testwork\Hook\Tester\Setup\HookedTeardown;
use Behat\Testwork\Output\Formatter;
use Behat\Testwork\Output\Printer\OutputPrinter; use Behat\Testwork\Output\Printer\OutputPrinter;
use Behat\Testwork\Tester\Result\TestResult; use Behat\Testwork\Tester\Setup\Setup;
use Behat\Testwork\Tester\Setup\Teardown;
use Moodle\BehatExtension\Driver\WebDriver; use Moodle\BehatExtension\Driver\WebDriver;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Prints hooks in a pretty fashion. * Prints hooks in a pretty fashion.
*
* @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class MoodleProgressPrinter implements SetupPrinter { final class MoodleProgressPrinter implements SetupPrinter {
@ -60,7 +56,10 @@ final class MoodleProgressPrinter implements SetupPrinter {
} }
/** /**
* {@inheritdoc} * Prints setup state.
*
* @param Formatter $formatter
* @param Setup $setup
*/ */
public function printSetup(Formatter $formatter, Setup $setup) { public function printSetup(Formatter $formatter, Setup $setup) {
if (empty(self::$outputdisplayed)) { if (empty(self::$outputdisplayed)) {
@ -70,15 +69,18 @@ final class MoodleProgressPrinter implements SetupPrinter {
} }
/** /**
* {@inheritdoc} * Prints teardown state.
*
* @param Formatter $formatter
* @param Teardown $teardown
*/ */
public function printTeardown(Formatter $formatter, Teardown $teardown) { public function printTeardown(Formatter $formatter, Teardown $teardown) {
if (!$teardown instanceof HookedTeardown) { if (!$teardown instanceof HookedTeardown) {
return; return;
} }
foreach ($teardown->getHookCallResults() as $callResult) { foreach ($teardown->getHookCallResults() as $callresult) {
$this->printTeardownHookCallResult($formatter->getOutputPrinter(), $callResult); $this->printTeardownHookCallResult($formatter->getOutputPrinter(), $callresult);
} }
} }
@ -105,20 +107,24 @@ final class MoodleProgressPrinter implements SetupPrinter {
* Prints teardown hook call result. * Prints teardown hook call result.
* *
* @param OutputPrinter $printer * @param OutputPrinter $printer
* @param CallResult $callResult * @param CallResult $callresult
*/ */
private function printTeardownHookCallResult(OutputPrinter $printer, CallResult $callResult) { private function printTeardownHookCallResult(OutputPrinter $printer, CallResult $callresult) {
// Notify dev that chained step is being used. // Notify dev that chained step is being used.
if (\Moodle\BehatExtension\EventDispatcher\Tester\ChainedStepTester::is_chained_step_used()) { if (\Moodle\BehatExtension\EventDispatcher\Tester\ChainedStepTester::is_chained_step_used()) {
$printer->writeln(); $printer->writeln();
$printer->write("{+failed}Chained steps are deprecated. See https://docs.moodle.org/dev/Acceptance_testing/Migrating_from_Behat_2.5_to_3.x_in_Moodle#Changes_required_in_context_file{-failed}"); $printer->write(
"{+failed}Chained steps are deprecated. " .
"See https://docs.moodle.org/dev/Acceptance_testing/" .
"Migrating_from_Behat_2.5_to_3.x_in_Moodle#Changes_required_in_context_file{-failed}"
);
} }
if (!$callResult->hasStdOut() && !$callResult->hasException()) { if (!$callresult->hasStdOut() && !$callresult->hasException()) {
return; return;
} }
$hook = $callResult->getCall()->getCallee(); $hook = $callresult->getCall()->getCallee();
$path = $hook->getPath(); $path = $hook->getPath();
$printer->writeln($hook); $printer->writeln($hook);

View file

@ -1,44 +1,60 @@
<?php <?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace Moodle\BehatExtension\ServiceContainer; namespace Moodle\BehatExtension\ServiceContainer;
use Symfony\Component\Config\FileLocator; use Behat\Behat\Definition\ServiceContainer\DefinitionExtension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Behat\Behat\EventDispatcher\ServiceContainer\EventDispatcherExtension;
use Behat\Behat\Gherkin\ServiceContainer\GherkinExtension;
use Behat\Behat\Tester\ServiceContainer\TesterExtension;
use Behat\Testwork\Cli\ServiceContainer\CliExtension;
use Behat\Testwork\Output\ServiceContainer\OutputExtension;
use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface; use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface;
use Behat\Testwork\ServiceContainer\ExtensionManager; use Behat\Testwork\ServiceContainer\ExtensionManager;
use Behat\Testwork\ServiceContainer\ServiceProcessor; use Behat\Testwork\ServiceContainer\ServiceProcessor;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Moodle\BehatExtension\Output\Formatter\MoodleProgressFormatterFactory;
use Behat\Behat\Tester\ServiceContainer\TesterExtension;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Behat\Behat\EventDispatcher\ServiceContainer\EventDispatcherExtension;
use Behat\Testwork\Suite\ServiceContainer\SuiteExtension;
use Behat\Behat\Definition\ServiceContainer\DefinitionExtension;
use Behat\Testwork\Cli\ServiceContainer\CliExtension;
use Behat\Behat\Definition\Printer\ConsoleDefinitionListPrinter;
use Behat\Behat\Gherkin\ServiceContainer\GherkinExtension;
use Behat\Testwork\Output\ServiceContainer\OutputExtension;
use Behat\Testwork\Specification\ServiceContainer\SpecificationExtension; use Behat\Testwork\Specification\ServiceContainer\SpecificationExtension;
use Behat\Testwork\Suite\ServiceContainer\SuiteExtension;
use Moodle\BehatExtension\Driver\WebDriverFactory; use Moodle\BehatExtension\Driver\WebDriverFactory;
use Moodle\BehatExtension\Output\Formatter\MoodleProgressFormatterFactory;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Behat extension for moodle * Behat extension for moodle
* *
* Provides multiple features directory loading (Gherkin\Loader\MoodleFeaturesSuiteLoader * Provides multiple features directory loading (Gherkin\Loader\MoodleFeaturesSuiteLoader
*
* @package core
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class BehatExtension implements ExtensionInterface { class BehatExtension implements ExtensionInterface {
/** /** @var string Extension configuration ID */
* Extension configuration ID.
*/
const MOODLE_ID = 'moodle'; const MOODLE_ID = 'moodle';
/** @var string Gherkin ID */
const GHERKIN_ID = 'gherkin'; const GHERKIN_ID = 'gherkin';
/** /** @var ServiceProcessor */
* @var ServiceProcessor
*/
private $processor; private $processor;
/** /**
@ -53,11 +69,11 @@ class BehatExtension implements ExtensionInterface {
/** /**
* Loads moodle specific configuration. * Loads moodle specific configuration.
* *
* @param array $config Extension configuration hash (from behat.yml)
* @param ContainerBuilder $container ContainerBuilder instance * @param ContainerBuilder $container ContainerBuilder instance
* @param array $config Extension configuration hash (from behat.yml)
*/ */
public function load(ContainerBuilder $container, array $config) { public function load(ContainerBuilder $container, array $config) {
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/services')); $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/services'));
$loader->load('core.xml'); $loader->load('core.xml');
// Getting the extension parameters. // Getting the extension parameters.
@ -96,13 +112,13 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function loadMoodleListFormatter(ContainerBuilder $container) { protected function loadMoodleListFormatter(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\Output\Formatter\MoodleListFormatter', array( $definition = new Definition('Moodle\BehatExtension\Output\Formatter\MoodleListFormatter', [
'moodle_list', 'moodle_list',
'List all scenarios. Use with --dry-run', 'List all scenarios. Use with --dry-run',
array('stepcount' => false), ['stepcount' => false],
$this->createOutputPrinterDefinition() $this->createOutputPrinterDefinition()
)); ]);
$definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 101)); $definition->addTag(OutputExtension::FORMATTER_TAG, ['priority' => 101]);
$container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodle_list', $definition); $container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodle_list', $definition);
} }
@ -112,13 +128,13 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function loadMoodleStepcountFormatter(ContainerBuilder $container) { protected function loadMoodleStepcountFormatter(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\Output\Formatter\MoodleStepcountFormatter', array( $definition = new Definition('Moodle\BehatExtension\Output\Formatter\MoodleStepcountFormatter', [
'moodle_stepcount', 'moodle_stepcount',
'Count steps in feature files. Use with --dry-run', 'Count steps in feature files. Use with --dry-run',
array('stepcount' => false), ['stepcount' => false],
$this->createOutputPrinterDefinition() $this->createOutputPrinterDefinition()
)); ]);
$definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 101)); $definition->addTag(OutputExtension::FORMATTER_TAG, ['priority' => 101]);
$container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodle_stepcount', $definition); $container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodle_stepcount', $definition);
} }
@ -128,13 +144,14 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function loadMoodleScreenshotFormatter(ContainerBuilder $container) { protected function loadMoodleScreenshotFormatter(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\Output\Formatter\MoodleScreenshotFormatter', array( $definition = new Definition('Moodle\BehatExtension\Output\Formatter\MoodleScreenshotFormatter', [
'moodle_screenshot', 'moodle_screenshot',
// phpcs:ignore Generic.Files.LineLength.TooLong
'Take screenshot of all steps. Use --format-settings \'{"formats": "html,image"}\' to get specific o/p type', 'Take screenshot of all steps. Use --format-settings \'{"formats": "html,image"}\' to get specific o/p type',
array('formats' => 'html,image'), ['formats' => 'html,image'],
$this->createOutputPrinterDefinition() $this->createOutputPrinterDefinition()
)); ]);
$definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 102)); $definition->addTag(OutputExtension::FORMATTER_TAG, ['priority' => 102]);
$container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodle_screenshot', $definition); $container->setDefinition(OutputExtension::FORMATTER_TAG . '.moodle_screenshot', $definition);
} }
@ -144,24 +161,24 @@ class BehatExtension implements ExtensionInterface {
* @return Definition * @return Definition
*/ */
protected function createOutputPrinterDefinition() { protected function createOutputPrinterDefinition() {
return new Definition('Behat\Testwork\Output\Printer\StreamOutputPrinter', array( return new Definition('Behat\Testwork\Output\Printer\StreamOutputPrinter', [
new Definition('Behat\Behat\Output\Printer\ConsoleOutputFactory'), new Definition('Behat\Behat\Output\Printer\ConsoleOutputFactory'),
)); ]);
} }
/** /**
* Loads skip passed controller. * Loads skip passed controller.
* *
* @param ContainerBuilder $container * @param ContainerBuilder $container
* @param null|string $cachePath * @param null|string $cachepath
*/ */
protected function loadSkipPassedController(ContainerBuilder $container, $cachePath) { protected function loadSkipPassedController(ContainerBuilder $container, $cachepath) {
$definition = new Definition('Moodle\BehatExtension\Tester\Cli\SkipPassedController', array( $definition = new Definition('Moodle\BehatExtension\Tester\Cli\SkipPassedController', [
new Reference(EventDispatcherExtension::DISPATCHER_ID), new Reference(EventDispatcherExtension::DISPATCHER_ID),
$cachePath, $cachepath,
$container->getParameter('paths.base') $container->getParameter('paths.base')
)); ]);
$definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 200)); $definition->addTag(CliExtension::CONTROLLER_TAG, ['priority' => 200]);
$container->setDefinition(CliExtension::CONTROLLER_TAG . '.passed', $definition); $container->setDefinition(CliExtension::CONTROLLER_TAG . '.passed', $definition);
} }
@ -171,11 +188,14 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
private function loadFilesystemSkipPassedScenariosListLocator(ContainerBuilder $container) { private function loadFilesystemSkipPassedScenariosListLocator(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\Locator\FilesystemSkipPassedListLocator', array( $definition = new Definition('Moodle\BehatExtension\Locator\FilesystemSkipPassedListLocator', [
new Reference(self::GHERKIN_ID) new Reference(self::GHERKIN_ID)
)); ]);
$definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 50)); $definition->addTag(SpecificationExtension::LOCATOR_TAG, ['priority' => 50]);
$container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_skip_passed_scenarios_list', $definition); $container->setDefinition(
SpecificationExtension::LOCATOR_TAG . '.filesystem_skip_passed_scenarios_list',
$definition
);
} }
/** /**
@ -184,15 +204,14 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
private function loadDefinitionPrinters(ContainerBuilder $container) { private function loadDefinitionPrinters(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\Definition\Printer\ConsoleDefinitionInformationPrinter', array( $definition = new Definition('Moodle\BehatExtension\Definition\Printer\ConsoleDefinitionInformationPrinter', [
new Reference(CliExtension::OUTPUT_ID), new Reference(CliExtension::OUTPUT_ID),
new Reference(DefinitionExtension::PATTERN_TRANSFORMER_ID), new Reference(DefinitionExtension::PATTERN_TRANSFORMER_ID),
new Reference(DefinitionExtension::DEFINITION_TRANSLATOR_ID), new Reference(DefinitionExtension::DEFINITION_TRANSLATOR_ID),
new Reference(GherkinExtension::KEYWORDS_ID) new Reference(GherkinExtension::KEYWORDS_ID)
)); ]);
$container->removeDefinition('definition.information_printer'); $container->removeDefinition('definition.information_printer');
$container->setDefinition('definition.information_printer', $definition); $container->setDefinition('definition.information_printer', $definition);
} }
/** /**
@ -201,12 +220,12 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
private function loadController(ContainerBuilder $container) { private function loadController(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\Definition\Cli\AvailableDefinitionsController', array( $definition = new Definition('Moodle\BehatExtension\Definition\Cli\AvailableDefinitionsController', [
new Reference(SuiteExtension::REGISTRY_ID), new Reference(SuiteExtension::REGISTRY_ID),
new Reference(DefinitionExtension::WRITER_ID), new Reference(DefinitionExtension::WRITER_ID),
new Reference('definition.list_printer'), new Reference('definition.list_printer'),
new Reference('definition.information_printer')) new Reference('definition.information_printer')
); ]);
$container->removeDefinition(CliExtension::CONTROLLER_TAG . '.available_definitions'); $container->removeDefinition(CliExtension::CONTROLLER_TAG . '.available_definitions');
$container->setDefinition(CliExtension::CONTROLLER_TAG . '.available_definitions', $definition); $container->setDefinition(CliExtension::CONTROLLER_TAG . '.available_definitions', $definition);
} }
@ -218,10 +237,10 @@ class BehatExtension implements ExtensionInterface {
*/ */
protected function loadChainedStepTester(ContainerBuilder $container) { protected function loadChainedStepTester(ContainerBuilder $container) {
// Chained steps. // Chained steps.
$definition = new Definition('Moodle\BehatExtension\EventDispatcher\Tester\ChainedStepTester', array( $definition = new Definition('Moodle\BehatExtension\EventDispatcher\Tester\ChainedStepTester', [
new Reference(TesterExtension::STEP_TESTER_ID), new Reference(TesterExtension::STEP_TESTER_ID),
)); ]);
$definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, array('priority' => 100)); $definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, ['priority' => 100]);
$container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.substep', $definition); $container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.substep', $definition);
} }
@ -231,11 +250,11 @@ class BehatExtension implements ExtensionInterface {
* @param ContainerBuilder $container * @param ContainerBuilder $container
*/ */
protected function loadEventDispatchingStepTester(ContainerBuilder $container) { protected function loadEventDispatchingStepTester(ContainerBuilder $container) {
$definition = new Definition('Moodle\BehatExtension\EventDispatcher\Tester\MoodleEventDispatchingStepTester', array( $definition = new Definition('Moodle\BehatExtension\EventDispatcher\Tester\MoodleEventDispatchingStepTester', [
new Reference(TesterExtension::STEP_TESTER_ID), new Reference(TesterExtension::STEP_TESTER_ID),
new Reference(EventDispatcherExtension::DISPATCHER_ID) new Reference(EventDispatcherExtension::DISPATCHER_ID)
)); ]);
$definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, array('priority' => -9999)); $definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, ['priority' => -9999]);
$container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); $container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.event_dispatching', $definition);
} }
@ -245,46 +264,62 @@ class BehatExtension implements ExtensionInterface {
* @param ArrayNodeDefinition $builder * @param ArrayNodeDefinition $builder
*/ */
public function configure(ArrayNodeDefinition $builder) { public function configure(ArrayNodeDefinition $builder) {
$builder-> // phpcs:disable PEAR.WhiteSpace.ObjectOperatorIndent.Incorrect
children()-> $builder->children()
arrayNode('capabilities')-> ->arrayNode('capabilities')
useAttributeAsKey('key')-> ->useAttributeAsKey('key')
prototype('variable')->end()-> ->prototype('variable')->end()
end()-> ->end()
arrayNode('steps_definitions')-> ->arrayNode('steps_definitions')
useAttributeAsKey('key')-> ->useAttributeAsKey('key')
prototype('variable')->end()-> ->prototype('variable')->end()
end()-> ->end()
scalarNode('moodledirroot')-> ->scalarNode('moodledirroot')
defaultNull()-> ->defaultNull()
end()-> ->end()
scalarNode('passed_cache')-> ->scalarNode('passed_cache')
info('Sets the passed cache path')-> ->info('Sets the passed cache path')
defaultValue( ->defaultValue(
is_writable(sys_get_temp_dir()) is_writable(sys_get_temp_dir())
? sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat_passed_cache' ? sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat_passed_cache'
: null)-> : null
end()-> )
end()-> ->end()
end(); ->end()
->end();
// phpcs:enable PEAR.WhiteSpace.ObjectOperatorIndent.Incorrect
} }
/** /**
* {@inheritDoc} * Returns the extension config key.
*
* @return string
*/ */
public function getConfigKey() { public function getConfigKey() {
return self::MOODLE_ID; return self::MOODLE_ID;
} }
/** /**
* {@inheritdoc} * Initializes other extensions.
*
* This method is called immediately after all extensions are activated but
* before any extension `configure()` method is called. This allows extensions
* to hook into the configuration of other extensions providing such an
* extension point.
*
* @param ExtensionManager $extensionmanager
*/ */
public function initialize(ExtensionManager $extensionManager) { public function initialize(ExtensionManager $extensionmanager) {
if (null !== $minkExtension = $extensionManager->getExtension('mink')) { if (null !== $minkextension = $extensionmanager->getExtension('mink')) {
$minkExtension->registerDriverFactory(new WebDriverFactory()); $minkextension->registerDriverFactory(new WebDriverFactory());
} }
} }
/**
* You can modify the container here before it is dumped to PHP code.
*
* @param ContainerBuilder $container
*/
public function process(ContainerBuilder $container) { public function process(ContainerBuilder $container) {
// Load controller for definition printing. // Load controller for definition printing.
$this->loadDefinitionPrinters($container); $this->loadDefinitionPrinters($container);

View file

@ -14,44 +14,39 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Caches passed scenarios and skip only them if `--skip-passed` option provided.
*
* @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace Moodle\BehatExtension\Tester\Cli; namespace Moodle\BehatExtension\Tester\Cli;
use Behat\Behat\EventDispatcher\Event\AfterFeatureTested;
use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; use Behat\Behat\EventDispatcher\Event\AfterScenarioTested;
use Behat\Behat\EventDispatcher\Event\ExampleTested; use Behat\Behat\EventDispatcher\Event\ExampleTested;
use Behat\Behat\EventDispatcher\Event\FeatureTested;
use Behat\Behat\EventDispatcher\Event\ScenarioTested; use Behat\Behat\EventDispatcher\Event\ScenarioTested;
use Behat\Testwork\Cli\Controller; use Behat\Testwork\Cli\Controller;
use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted;
use Behat\Testwork\Tester\Result\TestResult;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Behat\Testwork\Tester\Result\TestResult;
// phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod
/** /**
* Caches passed scenarios and skip only them if `--skip-passed` option provided. * Caches passed scenarios and skip only them if `--skip-passed` option provided.
* *
* @package core
* @copyright 2016 onwards Rajesh Taneja * @copyright 2016 onwards Rajesh Taneja
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
final class SkipPassedController implements Controller { final class SkipPassedController implements Controller {
/** /**
* @var EventDispatcherInterface * @var EventDispatcherInterface
*/ */
private $eventDispatcher; private $eventdispatcher;
/** /**
* @var null|string * @var null|string
*/ */
private $cachePath; private $cachepath;
/** /**
* @var string * @var string
@ -61,7 +56,7 @@ final class SkipPassedController implements Controller {
/** /**
* @var string[] * @var string[]
*/ */
private $lines = array(); private $lines = [];
/** /**
* @var string * @var string
@ -71,13 +66,13 @@ final class SkipPassedController implements Controller {
/** /**
* Initializes controller. * Initializes controller.
* *
* @param EventDispatcherInterface $eventDispatcher * @param EventDispatcherInterface $eventdispatcher
* @param null|string $cachePath * @param null|string $cachepath
* @param string $basepath * @param string $basepath
*/ */
public function __construct(EventDispatcherInterface $eventDispatcher, $cachePath, $basepath) { public function __construct(EventDispatcherInterface $eventdispatcher, $cachepath, $basepath) {
$this->eventDispatcher = $eventDispatcher; $this->eventdispatcher = $eventdispatcher;
$this->cachePath = null !== $cachePath ? rtrim($cachePath, DIRECTORY_SEPARATOR) : null; $this->cachepath = null !== $cachepath ? rtrim($cachepath, DIRECTORY_SEPARATOR) : null;
$this->basepath = $basepath; $this->basepath = $basepath;
} }
@ -112,9 +107,9 @@ final class SkipPassedController implements Controller {
return; return;
} }
$this->eventDispatcher->addListener(ScenarioTested::AFTER, array($this, 'collectPassedScenario'), -50); $this->eventdispatcher->addListener(ScenarioTested::AFTER, [$this, 'collectPassedScenario'], -50);
$this->eventDispatcher->addListener(ExampleTested::AFTER, array($this, 'collectPassedScenario'), -50); $this->eventdispatcher->addListener(ExampleTested::AFTER, [$this, 'collectPassedScenario'], -50);
$this->eventDispatcher->addListener(ExerciseCompleted::AFTER, array($this, 'writeCache'), -50); $this->eventdispatcher->addListener(ExerciseCompleted::AFTER, [$this, 'writeCache'], -50);
$this->key = $this->generateKey($input); $this->key = $this->generateKey($input);
if (!$this->getFileName() || !file_exists($this->getFileName())) { if (!$this->getFileName() || !file_exists($this->getFileName())) {
@ -141,8 +136,10 @@ final class SkipPassedController implements Controller {
$feature = $event->getFeature(); $feature = $event->getFeature();
$suitename = $event->getSuite()->getName(); $suitename = $event->getSuite()->getName();
if (($event->getTestResult()->getResultCode() !== TestResult::PASSED) && if (
($event->getTestResult()->getResultCode() !== TestResult::SKIPPED)) { ($event->getTestResult()->getResultCode() !== TestResult::PASSED) &&
($event->getTestResult()->getResultCode() !== TestResult::SKIPPED)
) {
unset($this->lines[$suitename][$feature->getFile()]); unset($this->lines[$suitename][$feature->getFile()]);
return; return;
} }
@ -172,7 +169,7 @@ final class SkipPassedController implements Controller {
*/ */
private function generateKey(InputInterface $input) { private function generateKey(InputInterface $input) {
return md5( return md5(
$input->getParameterOption(array('--profile', '-p')) . $input->getParameterOption(['--profile', '-p']) .
$input->getOption('suite') . $input->getOption('suite') .
implode(' ', $input->getOption('name')) . implode(' ', $input->getOption('name')) .
implode(' ', $input->getOption('tags')) . implode(' ', $input->getOption('tags')) .
@ -188,12 +185,12 @@ final class SkipPassedController implements Controller {
* @return null|string * @return null|string
*/ */
private function getFileName() { private function getFileName() {
if (null === $this->cachePath || null === $this->key) { if (null === $this->cachepath || null === $this->key) {
return null; return null;
} }
if (!is_dir($this->cachePath)) { if (!is_dir($this->cachepath)) {
mkdir($this->cachePath, 0777); mkdir($this->cachepath, 0777);
} }
return $this->cachePath . DIRECTORY_SEPARATOR . $this->key . '.passed'; return $this->cachepath . DIRECTORY_SEPARATOR . $this->key . '.passed';
} }
} }

View file

@ -1,5 +0,0 @@
This directory is a copy of original Moodle behat extension
located at https://github.com/moodlehq/moodle-behat-extension
The reason to move this code to Moodle core was to simplify
maintenance of behat integration.

View file

@ -14,13 +14,6 @@
<version>4.3.5</version> <version>4.3.5</version>
<licenseversion>2.0</licenseversion> <licenseversion>2.0</licenseversion>
</library> </library>
<library>
<location>behat/extension</location>
<name>Moodle behat extension</name>
<license>GPL</license>
<version>3.400.5</version>
<licenseversion>3.0+</licenseversion>
</library>
<library> <library>
<location>bennu</location> <location>bennu</location>
<name>Bennu</name> <name>Bennu</name>