From e1ad3a959d476c02a8da7d08e6ab245bb473f44e Mon Sep 17 00:00:00 2001
From: Rajesh Taneja <rajesh@moodle.com>
Date: Fri, 7 Oct 2016 10:55:41 +0800
Subject: [PATCH] MDL-55924 behat: Add core features to specified theme's

---
 admin/tool/behat/cli/init.php                | 11 +--
 admin/tool/behat/cli/util.php                | 16 +++--
 admin/tool/behat/cli/util_single_run.php     | 11 +--
 admin/tool/behat/tests/manager_util_test.php | 72 ++++++++++++++++++++
 lib/behat/classes/behat_config_util.php      | 26 +++++--
 lib/behat/classes/util.php                   |  2 +-
 6 files changed, 116 insertions(+), 22 deletions(-)

diff --git a/admin/tool/behat/cli/init.php b/admin/tool/behat/cli/init.php
index 48327c7814d..a5b66169f4b 100644
--- a/admin/tool/behat/cli/init.php
+++ b/admin/tool/behat/cli/init.php
@@ -47,13 +47,15 @@ list($options, $unrecognized) = cli_get_params(
         'help'     => false,
         'fromrun'  => 1,
         'torun'    => 0,
-        'run-with-theme' => false,
         'optimize-runs' => '',
+        'add-core-features-to-theme' => false,
     ),
     array(
         'j' => 'parallel',
         'm' => 'maxruns',
         'h' => 'help',
+        'o' => 'optimize-runs',
+        'a' => 'add-core-features-to-theme',
     )
 );
 
@@ -69,8 +71,9 @@ Options:
 -m, --maxruns    Max parallel processes to be executed at one time.
 --fromrun        Execute run starting from (Used for parallel runs on different vms)
 --torun          Execute run till (Used for parallel runs on different vms)
---optimize-runs  Split features with specified tags in all parallel runs.
---run-with-theme Run all core features with specified theme.
+
+-o, --optimize-runs Split features with specified tags in all parallel runs.
+-a, --add-core-features-to-theme Add all core features to specified theme's
 
 -h, --help     Print out this help
 
@@ -99,7 +102,7 @@ if ($options['parallel'] && $options['parallel'] > 1) {
     }
 } else {
     // Only sanitize options for single run.
-    $cmdoptionsforsinglerun = array('run-with-theme');
+    $cmdoptionsforsinglerun = array('add-core-features-to-theme');
 
     foreach ($cmdoptionsforsinglerun as $option) {
         if (!empty($options[$option])) {
diff --git a/admin/tool/behat/cli/util.php b/admin/tool/behat/cli/util.php
index a601967ae2e..b157ca7f757 100644
--- a/admin/tool/behat/cli/util.php
+++ b/admin/tool/behat/cli/util.php
@@ -56,13 +56,15 @@ list($options, $unrecognized) = cli_get_params(
         'updatesteps' => false,
         'fromrun'     => 1,
         'torun'       => 0,
-        'run-with-theme' => false,
         'optimize-runs' => '',
+        'add-core-features-to-theme' => false,
     ),
     array(
         'h' => 'help',
         'j' => 'parallel',
         'm' => 'maxruns',
+        'o' => 'optimize-runs',
+        'a' => 'add-core-features-to-theme',
     )
 );
 
@@ -81,10 +83,10 @@ Options:
 --diag         Get behat test environment status code
 --updatesteps  Update feature step file.
 
--j, --parallel   Number of parallel behat run operation
--m, --maxruns    Max parallel processes to be executed at one time.
---optimize-runs  Split features with specified tags in all parallel runs.
---run-with-theme Run all core features with specified theme.
+-j, --parallel Number of parallel behat run operation
+-m, --maxruns Max parallel processes to be executed at one time.
+-o, --optimize-runs Split features with specified tags in all parallel runs.
+-a, --add-core-features-to-theme Add all core features to specified theme's
 
 -h, --help     Print out this help
 
@@ -180,14 +182,14 @@ if ($options['diag'] || $options['enable'] || $options['disable']) {
 } else if ($options['updatesteps']) {
     // Rewrite config file to ensure we have all the features covered.
     if (empty($options['parallel'])) {
-        behat_config_manager::update_config_file('', true, '', $options['run-with-theme'], false, false);
+        behat_config_manager::update_config_file('', true, '', $options['add-core-features-to-theme'], false, false);
     } else {
         // Update config file, ensuring we have up-to-date behat.yml.
         for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
             $CFG->behatrunprocess = $i;
 
             // Update config file for each run.
-            behat_config_manager::update_config_file('', true, $options['optimize-runs'], $options['run-with-theme'],
+            behat_config_manager::update_config_file('', true, $options['optimize-runs'], $options['add-core-features-to-theme'],
                 $options['parallel'], $i);
         }
         unset($CFG->behatrunprocess);
diff --git a/admin/tool/behat/cli/util_single_run.php b/admin/tool/behat/cli/util_single_run.php
index 85987a0f1fa..3d0e2db310a 100644
--- a/admin/tool/behat/cli/util_single_run.php
+++ b/admin/tool/behat/cli/util_single_run.php
@@ -47,11 +47,13 @@ list($options, $unrecognized) = cli_get_params(
         'diag'        => false,
         'tags'        => '',
         'updatesteps' => false,
-        'run-with-theme' => false,
         'optimize-runs' => '',
+        'add-core-features-to-theme' => false,
     ),
     array(
         'h' => 'help',
+        'o' => 'optimize-runs',
+        'a' => 'add-core-features-to-theme',
     )
 );
 
@@ -73,8 +75,9 @@ Options:
 --disable        Disables test environment
 --diag           Get behat test environment status code
 --updatesteps    Update feature step file.
---optimize-runs  Split features with specified tags in all parallel runs.
---run-with-theme Run all core features with specified theme.
+
+-o, --optimize-runs Split features with specified tags in all parallel runs.
+-a, --add-core-features-to-theme Add all core features to specified theme's
 
 -h, --help Print out this help
 
@@ -180,7 +183,7 @@ if ($options['install']) {
     }
 
     // Enable test mode.
-    behat_util::start_test_mode($options['run-with-theme'], $options['optimize-runs'], $parallel, $run);
+    behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
 
     // This is only displayed once for parallel install.
     if (empty($run)) {
diff --git a/admin/tool/behat/tests/manager_util_test.php b/admin/tool/behat/tests/manager_util_test.php
index 78beb7ed24f..6ae0a6c1653 100644
--- a/admin/tool/behat/tests/manager_util_test.php
+++ b/admin/tool/behat/tests/manager_util_test.php
@@ -597,5 +597,77 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
         // There are 6 step definitions.
         $this->assertCount(6, $config['default']['extensions']['Moodle\BehatExtension']['steps_definitions']);
     }
+
+    /**
+     * Behat config for blacklisted tags.
+     */
+    public function test_core_features_to_include_in_specified_theme() {
+
+        $mockbuilder = $this->getMockBuilder('behat_config_util');
+        $mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes'));
+
+        $behatconfigutil = $mockbuilder->getMock();
+
+        $behatconfigutil = $this->get_behat_config_util($behatconfigutil);
+
+        // Check features when, no theme is specified.
+        $behatconfigutil->set_theme_suite_to_include_core_features('');
+        $config = $behatconfigutil->get_config_file_contents($this->corefatures, $this->corecontexts);
+        $suites = $config['default']['suites'];
+        foreach ($this->featurepaths as $themename => $paths) {
+            $this->assertCount(count($paths), $suites[$themename]['paths']);
+
+            foreach ($paths as $key => $feature) {
+                $this->assertContains($feature, $suites[$themename]['paths'][$key]);
+            }
+        }
+
+        // Check features when all themes are specified.
+        $featurepaths = $this->featurepaths;
+        $featurepaths['withfeatures'] = array_merge ($featurepaths['default'], $featurepaths['withfeatures']);
+        $featurepaths['nofeatures'] = array_merge ($featurepaths['default'], $featurepaths['nofeatures']);
+
+        $behatconfigutil->set_theme_suite_to_include_core_features('ALL');
+        $config = $behatconfigutil->get_config_file_contents($this->corefatures, $this->corecontexts);
+        $suites = $config['default']['suites'];
+        foreach ($featurepaths as $themename => $paths) {
+            $this->assertCount(count($paths), $suites[$themename]['paths']);
+
+            foreach ($paths as $key => $feature) {
+                $this->assertContains($feature, $suites[$themename]['paths'][$key]);
+            }
+        }
+
+        // Check features when all themes are specified.
+        $featurepaths = $this->featurepaths;
+        $featurepaths['withfeatures'] = array_merge ($featurepaths['default'], $featurepaths['withfeatures']);
+        $featurepaths['nofeatures'] = array_merge ($featurepaths['default'], $featurepaths['nofeatures']);
+
+        $behatconfigutil->set_theme_suite_to_include_core_features('withfeatures, nofeatures');
+        $config = $behatconfigutil->get_config_file_contents($this->corefatures, $this->corecontexts);
+        $suites = $config['default']['suites'];
+        foreach ($featurepaths as $themename => $paths) {
+            $this->assertCount(count($paths), $suites[$themename]['paths']);
+
+            foreach ($paths as $key => $feature) {
+                $this->assertContains($feature, $suites[$themename]['paths'][$key]);
+            }
+        }
+
+        // Check features when specified themes are passed..
+        $featurepaths = $this->featurepaths;
+        $featurepaths['nofeatures'] = array_merge ($featurepaths['default'], $featurepaths['nofeatures']);
+
+        $behatconfigutil->set_theme_suite_to_include_core_features('nofeatures');
+        $config = $behatconfigutil->get_config_file_contents($this->corefatures, $this->corecontexts);
+        $suites = $config['default']['suites'];
+        foreach ($featurepaths as $themename => $paths) {
+            $this->assertCount(count($paths), $suites[$themename]['paths']);
+
+            foreach ($paths as $key => $feature) {
+                $this->assertContains($feature, $suites[$themename]['paths'][$key]);
+            }
+        }
+    }
 }
 // @codeCoverageIgnoreEnd
diff --git a/lib/behat/classes/behat_config_util.php b/lib/behat/classes/behat_config_util.php
index 591f759e05d..8349f2d5bce 100644
--- a/lib/behat/classes/behat_config_util.php
+++ b/lib/behat/classes/behat_config_util.php
@@ -71,9 +71,9 @@ class behat_config_util {
     private $componentswithtests;
 
     /**
-     * @var bool keep track of theme to return suite with all core features included or not.
+     * @var array|string keep track of theme to return suite with all core features included or not.
      */
-    private $themesuitewithallfeatures = false;
+    private $themesuitewithallfeatures = array();
 
     /**
      * @var string filter features which have tags.
@@ -90,14 +90,27 @@ class behat_config_util {
      */
     private $currentrun = 0;
 
+    /**
+     * @var string used to specify if behat should be initialised with all themes.
+     */
+    const ALL_THEMES_TO_RUN = 'ALL';
+
     /**
      * Set value for theme suite to include all core features. This should be used if your want all core features to be
      * run with theme.
      *
-     * @param bool $val
+     * @param bool $themetoset
      */
-    public function set_theme_suite_to_include_core_features($val) {
-        $this->themesuitewithallfeatures = $val;
+    public function set_theme_suite_to_include_core_features($themetoset) {
+        // If no value passed to --run-with-theme or ALL is passed, then set core features for all themes.
+        if (!empty($themetoset)) {
+            if (is_number($themetoset) || is_bool($themetoset) || (self::ALL_THEMES_TO_RUN === strtoupper($themetoset))) {
+                $this->themesuitewithallfeatures = self::ALL_THEMES_TO_RUN;
+            } else {
+                $this->themesuitewithallfeatures = explode(',', $themetoset);
+                $this->themesuitewithallfeatures = array_map('trim', $this->themesuitewithallfeatures);
+            }
+        }
     }
 
     /**
@@ -1027,7 +1040,8 @@ class behat_config_util {
         foreach ($themes as $theme) {
             // Get list of features which will be included in theme.
             // If theme suite with all features is set, then we want all core features to be part of theme suite.
-            if ($this->themesuitewithallfeatures) {
+            if ((is_string($this->themesuitewithallfeatures) && ($this->themesuitewithallfeatures === self::ALL_THEMES_TO_RUN)) ||
+                in_array($theme, $this->themesuitewithallfeatures)) {
                 // If there is no theme specific feature. Then it's just core features.
                 if (empty($themefeatures[$theme]['features'])) {
                     $themesuitefeatures = $features;
diff --git a/lib/behat/classes/util.php b/lib/behat/classes/util.php
index 11aa8664b6e..9bb56b8ec19 100644
--- a/lib/behat/classes/util.php
+++ b/lib/behat/classes/util.php
@@ -215,7 +215,7 @@ class behat_util extends testing_util {
      *
      * Stores a file in dataroot/behat to allow Moodle to switch
      * to the test environment when using cli-server.
-     * @param bool $themesuitewithallfeatures if only theme specific features need to be included in the suite.
+     * @param bool $themesuitewithallfeatures List themes to include core features.
      * @param string $tags comma separated tag, which will be given preference while distributing features in parallel run.
      * @param int $parallelruns number of parallel runs.
      * @param int $run current run.