diff --git a/admin/tool/generator/classes/local/testscenario/runner.php b/admin/tool/generator/classes/local/testscenario/runner.php index ea9d0456259..8122cf5cadc 100644 --- a/admin/tool/generator/classes/local/testscenario/runner.php +++ b/admin/tool/generator/classes/local/testscenario/runner.php @@ -16,12 +16,15 @@ namespace tool_generator\local\testscenario; +use behat_admin; use behat_data_generators; +use behat_base; use Behat\Gherkin\Parser; use Behat\Gherkin\Lexer; use Behat\Gherkin\Keywords\ArrayKeywords; use ReflectionClass; use ReflectionMethod; +use stdClass; /** * Class to process a scenario generator file. @@ -72,6 +75,7 @@ class runner { require_once($CFG->libdir . '/behat/classes/behat_command.php'); require_once($CFG->libdir . '/behat/behat_base.php'); require_once("{$CFG->libdir}/tests/behat/behat_data_generators.php"); + require_once("{$CFG->dirroot}/admin/tests/behat/behat_admin.php"); return true; } @@ -81,6 +85,15 @@ class runner { private function load_generator() { $this->generator = new behat_data_generators(); $this->validsteps = $this->scan_generator($this->generator); + + // Set config values is not inside the general behat generators. + $extra = $this->scan_method( + new ReflectionMethod(behat_admin::class, 'the_following_config_values_are_set_as_admin'), + new behat_admin(), + ); + if ($extra) { + $this->validsteps[$extra->given] = $extra; + } } /** @@ -93,14 +106,32 @@ class runner { $class = new ReflectionClass($generator); $methods = $class->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { - $given = $this->get_method_given($method); - if ($given) { - $result[$given] = $method->getName(); + $scan = $this->scan_method($method, $generator); + if ($scan) { + $result[$scan->given] = $scan; } } return $result; } + /** + * Scan a method to get the given expression tag. + * @param ReflectionMethod $method the method to scan. + * @param behat_base $behatclass the behat class instance to use. + * @return stdClass|null the method data (given, name, class). + */ + private function scan_method(ReflectionMethod $method, behat_base $behatclass): ?stdClass { + $given = $this->get_method_given($method); + if (!$given) { + return null; + } + return (object)[ + 'given' => $given, + 'name' => $method->getName(), + 'generator' => $behatclass, + ]; + } + /** * Get the given expression tag of a method. * @@ -146,7 +177,7 @@ class runner { $result->add_scenario($scenario->getNodeType(), $scenario->getTitle()); $steps = $scenario->getSteps(); foreach ($steps as $step) { - $result->add_step(new steprunner($this->generator, $this->validsteps, $step)); + $result->add_step(new steprunner(null, $this->validsteps, $step)); } } } diff --git a/admin/tool/generator/classes/local/testscenario/steprunner.php b/admin/tool/generator/classes/local/testscenario/steprunner.php index e315640aad5..17b7834c276 100644 --- a/admin/tool/generator/classes/local/testscenario/steprunner.php +++ b/admin/tool/generator/classes/local/testscenario/steprunner.php @@ -16,7 +16,7 @@ namespace tool_generator\local\testscenario; -use behat_data_generators; +use behat_base; use Behat\Gherkin\Node\StepNode; /** @@ -27,8 +27,8 @@ use Behat\Gherkin\Node\StepNode; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class steprunner { - /** @var behat_data_generators the behat data generator instance. */ - private behat_data_generators $generator; + /** @var behat_base|null the behat step class instance. */ + private ?behat_base $generator = null; /** @var array the valid steps indexed by given expression tag. */ private array $validsteps; @@ -53,12 +53,14 @@ class steprunner { /** * Constructor. - * @param behat_data_generators $generator the behat data generator instance. + * @param behat_base|null $unused This does nothing, do not use it. * @param array $validsteps the valid steps indexed by given expression tag. * @param StepNode $stepnode the step node to process. */ - public function __construct(behat_data_generators $generator, array $validsteps, StepNode $stepnode) { - $this->generator = $generator; + public function __construct($unused, array $validsteps, StepNode $stepnode) { + if ($unused !== null) { + debugging('Deprecated argument passed to ' . __FUNCTION__, DEBUG_DEVELOPER); + } $this->validsteps = $validsteps; $this->stepnode = $stepnode; $this->init(); @@ -73,12 +75,13 @@ class steprunner { private function init() { $matches = []; $linetext = $this->stepnode->getText(); - foreach ($this->validsteps as $pattern => $method) { - if (!$this->match_given($pattern, $linetext, $matches)) { + foreach ($this->validsteps as $method) { + if (!$this->match_given($method->given, $linetext, $matches)) { continue; } - $this->method = $method; - $this->params = $this->build_method_params($method, $matches); + $this->method = $method->name; + $this->params = $this->build_method_params($method->name, $matches, $method->generator); + $this->generator = $method->generator; $this->isvalid = true; return; } @@ -89,10 +92,11 @@ class steprunner { * Build the method parameters. * @param string $methodname the method name. * @param array $matches the matches. + * @param behat_base $generator the method class. * @return array the method parameters. */ - private function build_method_params($methodname, $matches) { - $method = new \ReflectionMethod($this->generator, $methodname); + private function build_method_params(string $methodname, array $matches, behat_base $generator) { + $method = new \ReflectionMethod($generator, $methodname); $params = []; foreach ($method->getParameters() as $param) { $paramname = $param->getName(); diff --git a/admin/tool/generator/tests/behat/testscenario.feature b/admin/tool/generator/tests/behat/testscenario.feature index 41f641df82b..1a03a8bf065 100644 --- a/admin/tool/generator/tests/behat/testscenario.feature +++ b/admin/tool/generator/tests/behat/testscenario.feature @@ -21,6 +21,11 @@ Feature: Create testing scenarios using generators And I should see "Student Test3" And I should see "Student Test4" And I should see "Student Test5" + And I set the field "Participants tertiary navigation" to "Enrolment methods" + And I click on "Edit" "link" in the "Manual enrolments" "table_row" + And the field "Send course welcome message" matches value "No" + And I navigate to "Plugins > Enrolments > Manual enrolments" in site administration + And the field "Send course welcome message" matches value "No" @javascript Scenario: Prevent creating a testing scenario with no steps to execute diff --git a/admin/tool/generator/tests/fixtures/testscenario/scenario.feature b/admin/tool/generator/tests/fixtures/testscenario/scenario.feature index d228631ca0f..8993270dc69 100644 --- a/admin/tool/generator/tests/fixtures/testscenario/scenario.feature +++ b/admin/tool/generator/tests/fixtures/testscenario/scenario.feature @@ -1,6 +1,8 @@ Feature: Prepare scenario for testing Scenario: Create course content - Given the following "course" exists: + Given the following config values are set as admin: + | sendcoursewelcomemessage | 0 | enrol_manual | + And the following "course" exists: | fullname | Course test | | shortname | C1 | | category | 0 | diff --git a/admin/tool/generator/tests/local/testscenario/runner_test.php b/admin/tool/generator/tests/local/testscenario/runner_test.php index 835abeb61b1..42e2471cae8 100644 --- a/admin/tool/generator/tests/local/testscenario/runner_test.php +++ b/admin/tool/generator/tests/local/testscenario/runner_test.php @@ -46,7 +46,7 @@ class runner_test extends \advanced_testcase { $feature = $runner->parse_feature($contents); $this->assertEquals(2, count($feature->get_scenarios())); - $this->assertEquals(6, count($feature->get_all_steps())); + $this->assertEquals(7, count($feature->get_all_steps())); $this->assertTrue($feature->is_valid()); $result = $runner->execute($feature); diff --git a/admin/tool/generator/tests/local/testscenario/steprunner_test.php b/admin/tool/generator/tests/local/testscenario/steprunner_test.php index 08d20c567a1..9aeb6a88966 100644 --- a/admin/tool/generator/tests/local/testscenario/steprunner_test.php +++ b/admin/tool/generator/tests/local/testscenario/steprunner_test.php @@ -57,6 +57,31 @@ class steprunner_test extends \advanced_testcase { return $steps[0]; } + /** + * Get the list of valid behat steps for the tests. + * @return array the valid steps details. + */ + private function get_valid_steps(): array { + $generator = new behat_data_generators(); + return [ + '/^the following "(?P(?:[^"]|\\")*)" exist:$/' => (object) [ + 'name' => 'the_following_entities_exist', + 'given' => '/^the following "(?P(?:[^"]|\\")*)" exist:$/', + 'generator' => $generator, + ], + ':count :entitytype exist with the following data:' => (object) [ + 'name' => 'the_following_repeated_entities_exist', + 'given' => ':count :entitytype exist with the following data:', + 'generator' => $generator, + ], + 'the following :entitytype exists:' => (object) [ + 'name' => 'the_following_entity_exists', + 'given' => 'the following :entitytype exists:', + 'generator' => $generator, + ], + ]; + } + /** * Test for parse_feature. * @covers ::is_valid @@ -65,15 +90,9 @@ class steprunner_test extends \advanced_testcase { * @dataProvider execute_steps_provider */ public function test_is_valid(string $step, bool $expected): void { - $generator = new behat_data_generators(); - $validsteps = [ - '/^the following "(?P(?:[^"]|\\")*)" exist:$/' => 'the_following_entities_exist', - ':count :entitytype exist with the following data:' => 'the_following_repeated_entities_exist', - 'the following :entitytype exists:' => 'the_following_entity_exists', - ]; - + $validsteps = $this->get_valid_steps(); $step = $this->get_step($step); - $steprunner = new steprunner($generator, $validsteps, $step); + $steprunner = new steprunner(null, $validsteps, $step); $this->assertEquals($expected, $steprunner->is_valid()); } @@ -91,15 +110,10 @@ class steprunner_test extends \advanced_testcase { $this->resetAfterTest(); - $generator = new behat_data_generators(); - $validsteps = [ - '/^the following "(?P(?:[^"]|\\")*)" exist:$/' => 'the_following_entities_exist', - ':count :entitytype exist with the following data:' => 'the_following_repeated_entities_exist', - 'the following :entitytype exists:' => 'the_following_entity_exists', - ]; + $validsteps = $this->get_valid_steps(); $step = $this->get_step($step); - $steprunner = new steprunner($generator, $validsteps, $step); + $steprunner = new steprunner(null, $validsteps, $step); $this->assertFalse($steprunner->is_executed()); @@ -162,18 +176,13 @@ class steprunner_test extends \advanced_testcase { $this->resetAfterTest(); - $generator = new behat_data_generators(); - $validsteps = [ - '/^the following "(?P(?:[^"]|\\")*)" exist:$/' => 'the_following_entities_exist', - ':count :entitytype exist with the following data:' => 'the_following_repeated_entities_exist', - 'the following :entitytype exists:' => 'the_following_entity_exists', - ]; + $validsteps = $this->get_valid_steps(); $step = $this->get_step('Given the following "course" exists: | fullname | Course test | | shortname | C1 | | category | 0 |'); - $steprunner = new steprunner($generator, $validsteps, $step); + $steprunner = new steprunner(null, $validsteps, $step); $this->assertFalse($steprunner->is_executed()); @@ -190,7 +199,7 @@ class steprunner_test extends \advanced_testcase { ); // Execute the same course creation. - $steprunner = new steprunner($generator, $validsteps, $step); + $steprunner = new steprunner(null, $validsteps, $step); $this->assertFalse($steprunner->is_executed()); $result = $steprunner->execute(); $this->assertFalse($result); @@ -204,19 +213,14 @@ class steprunner_test extends \advanced_testcase { * @covers ::get_arguments_string */ public function test_get_step_content(): void { - $generator = new behat_data_generators(); - $validsteps = [ - '/^the following "(?P(?:[^"]|\\")*)" exist:$/' => 'the_following_entities_exist', - ':count :entitytype exist with the following data:' => 'the_following_repeated_entities_exist', - 'the following :entitytype exists:' => 'the_following_entity_exists', - ]; - $step = $this->get_step('Given the following "course" exists: - | fullname | Course test | - | shortname | C1 | - | category | 0 | - | numsections | 3 |'); - $steprunner = new steprunner($generator, $validsteps, $step); + | fullname | Course test | + | shortname | C1 | + | category | 0 | + | numsections | 3 |'); + + $validsteps = $this->get_valid_steps(); + $steprunner = new steprunner(null, $validsteps, $step); $this->assertEquals( 'the following "course" exists:',