diff --git a/src/Context/ContextDefinition.php b/src/Context/ContextDefinition.php
index 7122d6e..81cd878 100644
--- a/src/Context/ContextDefinition.php
+++ b/src/Context/ContextDefinition.php
@@ -25,6 +25,7 @@ class ContextDefinition extends ContextDefinitionCore implements ContextDefiniti
     'constraints' => 'constraints',
     'allow_null' => 'allowNull',
     'assignment_restriction' => 'assignmentRestriction',
+    'list_options_callback' => 'listOptionsCallback',
   ];
 
   /**
@@ -44,6 +45,13 @@ class ContextDefinition extends ContextDefinitionCore implements ContextDefiniti
   protected $assignmentRestriction = NULL;
 
   /**
+   * Name of callback function to generate options for select list.
+   *
+   * @var string|null
+   */
+  protected $listOptionsCallback = NULL;
+
+  /**
    * {@inheritdoc}
    */
   public function toArray() {
@@ -117,4 +125,18 @@ class ContextDefinition extends ContextDefinitionCore implements ContextDefiniti
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getListOptionsCallback() {
+    return $this->listOptionsCallback;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setListOptionsCallback($callback) {
+    $this->listOptionsCallback = $callback;
+  }
+
 }
diff --git a/src/Context/ContextDefinitionInterface.php b/src/Context/ContextDefinitionInterface.php
index 118627c..3648238 100644
--- a/src/Context/ContextDefinitionInterface.php
+++ b/src/Context/ContextDefinitionInterface.php
@@ -68,4 +68,22 @@ interface ContextDefinitionInterface extends ContextDefinitionInterfaceCore {
    */
   public function toArray();
 
+  /**
+   * Retrieves the select options callback.
+   *
+   * @return string
+   *   The name of the callback function to be used to generate options for a
+   *   select list in the UI.
+   */
+  public function getListOptionsCallback();
+
+  /**
+   * Sets the select options callback.
+   *
+   * @param string $name
+   *   The name of the callback function to be used to generate options for a
+   *   select list in the UI.
+   */
+  public function setListOptionsCallback($name);
+
 }
diff --git a/src/Form/Expression/ActionForm.php b/src/Form/Expression/ActionForm.php
index e93e6a0..f591a85 100644
--- a/src/Form/Expression/ActionForm.php
+++ b/src/Form/Expression/ActionForm.php
@@ -89,6 +89,8 @@ class ActionForm implements ExpressionFormInterface {
 
     $form['context']['#tree'] = TRUE;
     foreach ($context_definitions as $context_name => $context_definition) {
+      $list_callback = $context_definition->getListOptionsCallback();
+      $configuration['list_options'] = $list_callback == "" ? NULL : $action::$list_callback();
       $form = $this->buildContextForm($form, $form_state, $context_name, $context_definition, $configuration);
     }
 
diff --git a/src/Form/Expression/ConditionForm.php b/src/Form/Expression/ConditionForm.php
index c6ed139..963acea 100644
--- a/src/Form/Expression/ConditionForm.php
+++ b/src/Form/Expression/ConditionForm.php
@@ -91,6 +91,8 @@ class ConditionForm implements ExpressionFormInterface {
 
     $form['context']['#tree'] = TRUE;
     foreach ($context_definitions as $context_name => $context_definition) {
+      $list_callback = $context_definition->getListOptionsCallback();
+      $configuration['list_options'] = $list_callback == "" ? NULL : $condition::$list_callback();
       $form = $this->buildContextForm($form, $form_state, $context_name, $context_definition, $configuration);
     }
 
diff --git a/src/Form/Expression/ContextFormTrait.php b/src/Form/Expression/ContextFormTrait.php
index 65aeacc..e4aab12 100644
--- a/src/Form/Expression/ContextFormTrait.php
+++ b/src/Form/Expression/ContextFormTrait.php
@@ -51,15 +51,18 @@ trait ContextFormTrait {
     else {
       $default_value = $context_definition->getDefaultValue();
     }
+    // Set initial values for the input field.
     $form['context'][$context_name]['setting'] = [
       '#type' => 'textfield',
       '#title' => $title,
       '#required' => $context_definition->isRequired(),
       '#default_value' => $default_value,
+      '#multiple' => $context_definition->isMultiple(),
     ];
 
     $element = &$form['context'][$context_name]['setting'];
 
+    // Modify the element if doing data selection.
     if ($mode == 'selector') {
       $element['#description'] = $this->t("The data selector helps you drill down into the data available to Rules. <em>To make entity fields appear in the data selector, you may have to use the condition 'entity has field' (or 'content is of type').</em> More useful tips about data selection is available in <a href=':url'>the online documentation</a>.", [
         ':url' => 'https://www.drupal.org/node/1300042',
@@ -70,16 +73,25 @@ trait ContextFormTrait {
       $element['#attributes']['data-autocomplete-path'] = $url->toString();
       $element['#attached']['library'][] = 'rules/rules.autocomplete';
     }
+    // Modify the element if it is a selection list.
+    elseif (!empty($configuration['list_options'])) {
+      $element['#type'] = 'select';
+      $element['#options'] = $configuration['list_options'];
+      $element['#description'] = $element['#multiple'] ? $this->t('Select any number of values.') : $this->t('Select a value from the list.');
+    }
+    // Modify the element to allow multiple text entries using textarea.
     elseif ($context_definition->isMultiple()) {
       $element['#type'] = 'textarea';
-      // @todo get a description for possible values that can be filled in.
       $element['#description'] = $this->t('Enter one value per line for this multi-valued context.');
-
       // Glue the list of values together as one item per line in the text area.
       if (is_array($default_value)) {
         $element['#default_value'] = implode("\n", $default_value);
       }
     }
+    // The element is a simple single entry text field.
+    else {
+      $element['#description'] = $this->t('Enter the value directly.');
+    }
 
     $value = $mode == 'selector' ? $this->t('Switch to the direct input mode') : $this->t('Switch to data selection');
     $form['context'][$context_name]['switch_button'] = [
@@ -113,10 +125,16 @@ trait ContextFormTrait {
         $context_config->map($context_name, $value['setting']);
       }
       else {
-        // Each line of the textarea is one value for multiple contexts.
         if ($context_definitions[$context_name]->isMultiple()) {
-          $values = explode("\n", $value['setting']);
-          $context_config->setValue($context_name, $values);
+          if (!empty($context_definitions[$context_name]->getListOptionsCallback())) {
+            // This is a select list with multiple values allowed.
+            $context_config->setValue($context_name, array_keys($value['setting']));
+          }
+          else {
+            // Each line of the textarea is one value for multiple contexts.
+            $values = explode("\n", $value['setting']);
+            $context_config->setValue($context_name, $values);
+          }
         }
         else {
           $context_config->setValue($context_name, $value['setting']);
diff --git a/src/Plugin/Condition/EntityHasField.php b/src/Plugin/Condition/EntityHasField.php
index dfb5dbe..03f5cd7 100644
--- a/src/Plugin/Condition/EntityHasField.php
+++ b/src/Plugin/Condition/EntityHasField.php
@@ -19,7 +19,8 @@ use Drupal\rules\Core\RulesConditionBase;
  *     ),
  *     "field" = @ContextDefinition("string",
  *       label = @Translation("Field"),
- *       description = @Translation("The name of the field to check for.")
+ *       description = @Translation("The name of the field to check for."),
+ *       list_options_callback = "fieldListOptions"
  *     )
  *   }
  * )
@@ -43,4 +44,28 @@ class EntityHasField extends RulesConditionBase {
     return $entity->hasField($field);
   }
 
+  /**
+   * Returns all the available fields in the system.
+   *
+   * @return array
+   *   An array of field names keyed on the field name.
+   */
+  public static function fieldListOptions() {
+    $options = [];
+
+    // Load all the fields in the system.
+    $fields = \Drupal::service('entity_field.manager')->getFieldMap();
+
+    // Add each field to our options array.
+    foreach ($fields as $entity_fields) {
+      foreach ($entity_fields as $field_name => $field) {
+        $options[$field_name] = $field_name;
+      }
+    }
+    // Sort the field names for ease of locating and selecting.
+    asort($options);
+
+    return $options;
+  }
+
 }
diff --git a/src/Plugin/Condition/EntityIsOfBundle.php b/src/Plugin/Condition/EntityIsOfBundle.php
index 449b4e8..06230d2 100644
--- a/src/Plugin/Condition/EntityIsOfBundle.php
+++ b/src/Plugin/Condition/EntityIsOfBundle.php
@@ -4,6 +4,7 @@ namespace Drupal\rules\Plugin\Condition;
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\rules\Core\RulesConditionBase;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
 
 /**
  * Provides an 'Entity is of bundle' condition.
@@ -20,11 +21,13 @@ use Drupal\rules\Core\RulesConditionBase;
  *     ),
  *     "type" = @ContextDefinition("string",
  *       label = @Translation("Type"),
- *       description = @Translation("The type of the evaluated entity.")
+ *       description = @Translation("The type of the evaluated entity."),
+ *       list_options_callback = "entityTypesListOptions"
  *     ),
  *     "bundle" = @ContextDefinition("string",
  *       label = @Translation("Bundle"),
- *       description = @Translation("The bundle of the evaluated entity.")
+ *       description = @Translation("The bundle of the evaluated entity."),
+ *       list_options_callback = "bundleListOptions"
  *     )
  *   }
  * )
@@ -69,4 +72,48 @@ class EntityIsOfBundle extends RulesConditionBase {
     return $changed_definitions;
   }
 
+  /**
+   * Returns an array of entity types that exist in the system.
+   *
+   * @return array
+   *   An array of entity types keyed on the entity type machine name.
+   */
+  public static function entityTypesListOptions() {
+    $options = [];
+
+    $entity_types = \Drupal::entityTypeManager()->getDefinitions();
+
+    foreach ($entity_types as $entity_type) {
+      if (!$entity_type instanceof ContentEntityTypeInterface) {
+        continue;
+      }
+
+      $options[$entity_type->id()] = $entity_type->getLabel();
+    }
+
+    return $options;
+  }
+
+  /**
+   * Returns an array of entity bundles options.
+   *
+   * @return array
+   *   An array of bundles keyed on the bundle machine name.
+   */
+  public static function bundleListOptions() {
+    $options = [];
+
+    $entity_types = \Drupal::entityTypeManager()->getDefinitions();
+
+    foreach ($entity_types as $entity_type) {
+      if ($bundle_entity_type = $entity_type->getBundleEntityType()) {
+        foreach (\Drupal::entityTypeManager()->getStorage($bundle_entity_type)->loadMultiple() as $entity) {
+          $options[$entity->id()] = $entity->label();
+        }
+      }
+    }
+
+    return $options;
+  }
+
 }
diff --git a/src/Plugin/Condition/EntityIsOfType.php b/src/Plugin/Condition/EntityIsOfType.php
index f915172..4ab7835 100644
--- a/src/Plugin/Condition/EntityIsOfType.php
+++ b/src/Plugin/Condition/EntityIsOfType.php
@@ -4,6 +4,7 @@ namespace Drupal\rules\Plugin\Condition;
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\rules\Core\RulesConditionBase;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
 
 /**
  * Provides an 'Entity is of type' condition.
@@ -19,7 +20,8 @@ use Drupal\rules\Core\RulesConditionBase;
  *     ),
  *     "type" = @ContextDefinition("string",
  *       label = @Translation("Type"),
- *       description = @Translation("The entity type specified by the condition.")
+ *       description = @Translation("The entity type specified by the condition."),
+ *       list_options_callback = "entityTypesListOptions"
  *     )
  *   }
  * )
@@ -46,4 +48,26 @@ class EntityIsOfType extends RulesConditionBase {
     return $entity_type == $type;
   }
 
+  /**
+   * Returns an array of entity types that exist in the system.
+   *
+   * @return array
+   *   An array of entity types keyed on the entity type machine name.
+   */
+  public static function entityTypesListOptions() {
+    $options = [];
+
+    $entity_types = \Drupal::entityTypeManager()->getDefinitions();
+
+    foreach ($entity_types as $entity_type) {
+      if (!$entity_type instanceof ContentEntityTypeInterface) {
+        continue;
+      }
+
+      $options[$entity_type->id()] = $entity_type->getLabel();
+    }
+
+    return $options;
+  }
+
 }
diff --git a/src/Plugin/Condition/NodeIsOfType.php b/src/Plugin/Condition/NodeIsOfType.php
index 9ee4ab8..16cd031 100644
--- a/src/Plugin/Condition/NodeIsOfType.php
+++ b/src/Plugin/Condition/NodeIsOfType.php
@@ -19,7 +19,8 @@ use Drupal\rules\Core\RulesConditionBase;
  *     "types" = @ContextDefinition("string",
  *       label = @Translation("Content types"),
  *       description = @Translation("Check for the the allowed node types."),
- *       multiple = TRUE
+ *       multiple = TRUE,
+ *       list_options_callback = "nodeTypesListOptions"
  *     )
  *   }
  * )
@@ -41,4 +42,22 @@ class NodeIsOfType extends RulesConditionBase {
     return in_array($node->getType(), $types);
   }
 
+  /**
+   * Returns an array of node types that exist in the system.
+   *
+   * @return array
+   *   An array of node types keyed on the node type machine name.
+   */
+  public static function nodeTypesListOptions() {
+    $options = [];
+
+    $node_types = \Drupal::service('entity.manager')->getStorage('node_type')->loadMultiple();
+
+    foreach ($node_types as $node_type) {
+      $options[$node_type->id()] = $node_type->label();
+    }
+
+    return $options;
+  }
+
 }
diff --git a/src/Plugin/Condition/UserHasEntityFieldAccess.php b/src/Plugin/Condition/UserHasEntityFieldAccess.php
index a0bdf2e..6c7d3e0 100644
--- a/src/Plugin/Condition/UserHasEntityFieldAccess.php
+++ b/src/Plugin/Condition/UserHasEntityFieldAccess.php
@@ -17,18 +17,23 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  *   label = @Translation("User has entity field access"),
  *   category = @Translation("User"),
  *   context = {
+ *     "user" = @ContextDefinition("entity:user",
+ *       label = @Translation("User")
+ *     ),
  *     "entity" = @ContextDefinition("entity",
  *       label = @Translation("Entity")
  *     ),
  *     "field" = @ContextDefinition("string",
- *       label = @Translation("Field")
+ *       label = @Translation("Field"),
+ *       description = @Translation("The name of the field to check."),
+ *       list_options_callback = "fieldListOptions"
  *     ),
  *     "operation" = @ContextDefinition("string",
- *       label = @Translation("Operation")
+ *       label = @Translation("Operation"),
+ *       description = @Translation("The access to check for."),
+ *       list_options_callback = "accessListOptions",
+ *       default_value = "view",
  *     ),
- *     "user" = @ContextDefinition("entity:user",
- *       label = @Translation("User")
- *     )
  *   }
  * )
  *
@@ -75,6 +80,8 @@ class UserHasEntityFieldAccess extends RulesConditionBase implements ContainerFa
   /**
    * Evaluate if the user has access to the field of an entity.
    *
+   * @param \Drupal\Core\Session\AccountInterface $user
+   *   The user account to test access against.
    * @param \Drupal\Core\Entity\ContentEntityInterface $entity
    *   The entity to check access on.
    * @param string $field
@@ -82,13 +89,11 @@ class UserHasEntityFieldAccess extends RulesConditionBase implements ContainerFa
    * @param string $operation
    *   The operation access should be checked for. Usually one of "view" or
    *   "edit".
-   * @param \Drupal\Core\Session\AccountInterface $user
-   *   The user account to test access against.
    *
    * @return bool
    *   TRUE if the user has access to the field on the entity, FALSE otherwise.
    */
-  protected function doEvaluate(ContentEntityInterface $entity, $field, $operation, AccountInterface $user) {
+  protected function doEvaluate(AccountInterface $user, ContentEntityInterface $entity, $field, $operation) {
     if (!$entity->hasField($field)) {
       return FALSE;
     }
@@ -103,4 +108,38 @@ class UserHasEntityFieldAccess extends RulesConditionBase implements ContainerFa
     return $access->fieldAccess($operation, $definition, $user, $items);
   }
 
+  /**
+   * Returns all the available fields in the system.
+   *
+   * @return array
+   *   An array of field names keyed on the field name.
+   */
+  public static function fieldListOptions() {
+    $options = [];
+
+    // Load all the fields in the system.
+    $fields = \Drupal::service('entity_field.manager')->getFieldMap();
+
+    // Add each field to our options array.
+    foreach ($fields as $entity_fields) {
+      foreach ($entity_fields as $field_name => $field) {
+        $options[$field_name] = $field_name;
+      }
+    }
+    // Sort the field names for ease of locating and selecting.
+    asort($options);
+
+    return $options;
+  }
+
+  /**
+   * Returns the types of field access to check for.
+   *
+   * @return array
+   *   An array of access types.
+   */
+  public static function accessListOptions() {
+    return ['view' => t('View'), 'edit' => t('Edit')];
+  }
+
 }
diff --git a/src/Plugin/Condition/UserHasRole.php b/src/Plugin/Condition/UserHasRole.php
index 46c1166..dacfe88 100644
--- a/src/Plugin/Condition/UserHasRole.php
+++ b/src/Plugin/Condition/UserHasRole.php
@@ -19,12 +19,14 @@ use Drupal\user\UserInterface;
  *     ),
  *     "roles" = @ContextDefinition("entity:user_role",
  *       label = @Translation("Roles"),
- *       multiple = TRUE
+ *       multiple = TRUE,
+ *       list_options_callback = "userRolesListOptions"
  *     ),
  *     "operation" = @ContextDefinition("string",
- *       label = @Translation("Match roles"),
- *       description = @Translation("If matching against all selected roles, the user must have <em>all</em> the roles selected."),
+ *       label = @Translation("Matching multiple roles"),
+ *       description = @Translation("Specify if the user must have <em>all</em> the roles selected or <em>any</em> of the roles selected."),
  *       default_value = "AND",
+ *       list_options_callback = "operationListOptions",
  *       required = FALSE
  *     )
  *   }
@@ -67,4 +69,27 @@ class UserHasRole extends RulesConditionBase {
     }
   }
 
+  /**
+   * Returns an array of user role options.
+   *
+   * @return array
+   *   An array of user roles keyed on role name.
+   */
+  public static function userRolesListOptions() {
+    return user_role_names(TRUE);
+  }
+
+  /**
+   * Returns an array of role matching options.
+   *
+   * @return array
+   *   An array of logic operations for multiple role matching.
+   */
+  public static function operationListOptions() {
+    return [
+      'AND' => 'All selected roles (and)',
+      'OR' => 'Any selected role (or)',
+    ];
+  }
+
 }
diff --git a/src/Plugin/RulesAction/SystemMessage.php b/src/Plugin/RulesAction/SystemMessage.php
index 0c13e6a..0aaffad 100644
--- a/src/Plugin/RulesAction/SystemMessage.php
+++ b/src/Plugin/RulesAction/SystemMessage.php
@@ -17,13 +17,15 @@ use Drupal\rules\Core\RulesActionBase;
  *       label = @Translation("Message")
  *     ),
  *     "type" = @ContextDefinition("string",
- *       label = @Translation("Message type")
+ *       label = @Translation("Message type"),
+ *       list_options_callback = "messageTypeListOptions"
  *     ),
  *     "repeat" = @ContextDefinition("boolean",
  *       label = @Translation("Repeat message"),
  *       description = @Translation("If disabled and the message has been already shown, then the message won't be repeated."),
  *       default_value = NULL,
- *       required = FALSE
+ *       required = FALSE,
+ *       list_options_callback = "repeatListOptions"
  *     )
  *   }
  * )
@@ -50,4 +52,32 @@ class SystemMessage extends RulesActionBase {
     drupal_set_message($message, $type, $repeat);
   }
 
+  /**
+   * Returns an array of statuses that we can set for the drupal_set_message().
+   *
+   * @return array
+   *   An array of status options keyed on the status name.
+   */
+  public static function messageTypeListOptions() {
+    return [
+      'info' => t('Info'),
+      'status' => t('Status'),
+      'warning' => t('Warning'),
+      'error' => t('Error'),
+    ];
+  }
+
+  /**
+   * Returns a YES/NO option set for selecting whether to repeat the message.
+   *
+   * @return array
+   *   A YES/NO options array.
+   */
+  public static function repeatListOptions() {
+    return [
+      0 => t('No'),
+      1 => t('Yes'),
+    ];
+  }
+
 }
diff --git a/src/Plugin/RulesAction/UserRoleAdd.php b/src/Plugin/RulesAction/UserRoleAdd.php
index 7cfc0a1..cd6ce17 100644
--- a/src/Plugin/RulesAction/UserRoleAdd.php
+++ b/src/Plugin/RulesAction/UserRoleAdd.php
@@ -19,7 +19,8 @@ use Drupal\user\UserInterface;
  *     ),
  *     "roles" = @ContextDefinition("entity:user_role",
  *       label = @Translation("Roles"),
- *       multiple = TRUE
+ *       multiple = TRUE,
+ *       list_options_callback = "userRolesListOptions"
  *     )
  *   }
  * )
@@ -75,4 +76,14 @@ class UserRoleAdd extends RulesActionBase {
     return [];
   }
 
+  /**
+   * Returns an array of user role options.
+   *
+   * @return array
+   *   An array of user roles keyed on role name.
+   */
+  public static function userRolesListOptions() {
+    return user_role_names(TRUE);
+  }
+
 }
diff --git a/src/Plugin/RulesAction/UserRoleRemove.php b/src/Plugin/RulesAction/UserRoleRemove.php
index aa03ffe..8207c59 100644
--- a/src/Plugin/RulesAction/UserRoleRemove.php
+++ b/src/Plugin/RulesAction/UserRoleRemove.php
@@ -19,7 +19,8 @@ use Drupal\rules\Exception\InvalidArgumentException;
  *     ),
  *     "roles" = @ContextDefinition("entity:user_role",
  *       label = @Translation("Roles"),
- *       multiple = TRUE
+ *       multiple = TRUE,
+ *       list_options_callback = "userRolesListOptions"
  *     )
  *   }
  * )
@@ -72,4 +73,14 @@ class UserRoleRemove extends RulesActionBase {
     return [];
   }
 
+  /**
+   * Returns an array of user role options.
+   *
+   * @return array
+   *   An array of user roles keyed on role name.
+   */
+  public static function userRolesListOptions() {
+    return user_role_names(TRUE);
+  }
+
 }
diff --git a/tests/src/Functional/ConfigureAndExecuteTest.php b/tests/src/Functional/ConfigureAndExecuteTest.php
index 9c1edb9..8b4deed 100644
--- a/tests/src/Functional/ConfigureAndExecuteTest.php
+++ b/tests/src/Functional/ConfigureAndExecuteTest.php
@@ -14,7 +14,7 @@ class ConfigureAndExecuteTest extends RulesBrowserTestBase {
    *
    * @var array
    */
-  public static $modules = ['node', 'rules'];
+  public static $modules = ['node', 'rules', 'comment'];
 
   /**
    * We use the minimal profile because we want to test local action links.
@@ -38,32 +38,46 @@ class ConfigureAndExecuteTest extends RulesBrowserTestBase {
     $type->save();
     $this->container->get('router.builder')->rebuild();
 
-  }
-
-  /**
-   * Tests creation of a rule and then triggering its execution.
-   */
-  public function testConfigureAndExecute() {
-    $account = $this->drupalCreateUser([
+    $this->account = $this->drupalCreateUser([
       'create article content',
       'administer rules',
       'administer site configuration',
     ]);
-    $this->drupalLogin($account);
+    $this->drupalLogin($this->account);
+  }
 
+  /**
+   * Helper function to create a reaction rule.
+   *
+   * @param string $label
+   *   The label for the new rule.
+   * @param string $machine_name
+   *   The internal machine-readable name.
+   * @param string $event
+   *   The name of the event to react on.
+   * @param string $description
+   *   Optional description for the reaction rule.
+   */
+  private function createRule($label, $machine_name, $event, $description = '') {
     $this->drupalGet('admin/config/workflow/rules');
+    $this->clickLink('Add reaction rule');
+    $this->fillField('Label', $label);
+    $this->fillField('Machine-readable name', $machine_name);
+    $this->fillField('React on event', $event);
+    $this->fillField('Description', $description);
+    $this->pressButton('Save');
+  }
+
+  /**
+   * Tests creation of a rule and then triggering its execution.
+   */
+  public function testConfigureAndExecute() {
 
     // Set up a rule that will show a system message if the title of a node
     // matches "Test title".
-    $this->clickLink('Add reaction rule');
-
-    $this->fillField('Label', 'Test rule');
-    $this->fillField('Machine-readable name', 'test_rule');
-    $this->fillField('React on event', 'rules_entity_presave:node');
-    $this->pressButton('Save');
+    $this->createRule('Test rule', 'test_rule', 'rules_entity_presave:node');
 
     $this->clickLink('Add condition');
-
     $this->fillField('Condition', 'rules_data_comparison');
     $this->pressButton('Continue');
 
@@ -110,4 +124,269 @@ class ConfigureAndExecuteTest extends RulesBrowserTestBase {
     $this->assertSession()->pageTextNotContains('Title matched "Test title"!');
   }
 
+  /**
+   * Test to add each condition provided by Rules.
+   *
+   * @param string $id
+   *   The id of the condition.
+   * @param string $label
+   *   The label of the condition.
+   * @param array $required
+   *   Array of fields to fill. The key is form field name and the value is the
+   *   text to fill into the field. This should hold just the fields which are
+   *   required and do not have any default value. Use an empty array if there
+   *   are no fields or all fields have a default.
+   * @param array $defaults
+   *   Array of defaults which should be stored without having to select the
+   *   value in the form.
+   *
+   * @dataProvider dataAddConditions()
+   */
+  public function testAddConditions($id, $label, array $required = [], array $defaults = []) {
+    $this->createRule('Add condition ' . $id, 'test_rule', 'rules_entity_presave:node', "Add condition $label\nid=$id");
+    $this->clickLink('Add condition');
+    $this->fillField('Condition', $id);
+    $this->pressButton('Continue');
+
+    // Save the form. If $required is not empty then we should get error(s) so
+    // verify this, then fill in the specified fields and try to save again.
+    $this->pressButton('Save');
+    if (!empty($required)) {
+      // Check that an error message is shown.
+      $this->assertSession()->pageTextContains('Error message');
+      // Fill in the required fields.
+      foreach ($required as $field => $value) {
+        $this->fillField($field, $value);
+      }
+      $this->pressButton('Save');
+    }
+    // Assert that the rule has saved correctly with no error message.
+    $this->assertSession()->pageTextNotContains('Error message');
+    $this->assertSession()->pageTextContains('Edit reaction rule "Add condition ' . $id . '"');
+    $this->assertSession()->pageTextContains('Condition: ' . $label);
+    // @todo - check that all values ($required and $defaults) have been stored.
+  }
+
+  /**
+   * Provides data for testAddConditions().
+   *
+   * @return array
+   *   The test data.
+   */
+  public function dataAddConditions() {
+    return [
+      // Data.
+      'Data Comparison' => [
+        'rules_data_comparison',
+        'Data Comparison',
+        ['context[data][setting]' => 'node.status.value', 'context[value][setting]' => TRUE],
+        ['operation' => '=='],
+      ],
+      'Data Is Empty' => [
+        'rules_data_is_empty',
+        'Data value is empty',
+        ['context[data][setting]' => 'node.uid.entity.name.value'],
+      ],
+      /*
+       // The two 'list' conditions do not work yet.
+      'List contains' => [
+        'rules_list_contains',
+        'List contains item',
+        ['context[list][setting]' => 'list_a', 'context[item][setting]' => '1'],
+      ],
+      'List count' => [
+        'rules_list_count_is',
+        'List Count Comparison',
+        ['context[list][setting]' => 'list_b', 'context[value][setting]' => 3],
+        ['operator' => '=='],
+      ],
+       */
+      // Entity.
+      'Entity has field' => [
+        'rules_entity_has_field',
+        'Entity has field',
+        ['context[entity][setting]' => 'node', 'context[field][setting]' => 'mail'],
+      ],
+      'Entity is new' => [
+        'rules_entity_is_new',
+        'Entity is new',
+        ['context[entity][setting]' => 'node'],
+      ],
+      'Entity is Bundle' => [
+        'rules_entity_is_of_bundle',
+        'Entity is of bundle', [
+          'context[entity][setting]' => 'node',
+          'context[type][setting]' => 'node',
+          'context[bundle][setting]' => 'article',
+        ],
+      ],
+      'Entity is Type' => [
+        'rules_entity_is_of_type',
+        'Entity is of TYPE',
+        ['context[entity][setting]' => 'something' , 'context[type][setting]' => 'user'],
+      ],
+      // Node.
+      'Node is promoted' => [
+        'rules_node_is_promoted',
+        'Node is promoted',
+        ['context[node][setting]' => 'node'],
+      ],
+      'Node is published' => [
+        'rules_node_is_published',
+        'Node is published',
+        ['context[node][setting]' => 'node'],
+      ],
+      'Node is sticky' => [
+        'rules_node_is_sticky',
+        'Node is sticky',
+        ['context[node][setting]' => 'anything'],
+      ],
+      'Node is Type' => [
+        'rules_node_is_of_type',
+        'Node is of type',
+        ['context[node][setting]' => 'something', 'edit-context-types-setting' => 'article'],
+      ],
+      // Path.
+      'Path alias exists' => [
+        'rules_path_alias_exists',
+        'Path alias exists',
+        ['context[alias][setting]' => 'something'],
+        ['context[language][setting]' => 'something'],
+      ],
+      'Path has alias' => [
+        'rules_path_has_alias',
+        'Path has alias',
+        ['context[path][setting]' => 'something'],
+        ['context[language][setting]' => 'something'],
+      ],
+      // User.
+      'User has entity field access' => [
+        'rules_entity_field_access',
+        'User has entity field access', [
+          'context[entity][setting]' => 'something',
+          'context[field][setting]' => 'mail',
+          'context[user][setting]' => 'someone',
+        ],
+        ['context[operation][setting]' => 'view'],
+      ],
+      'User has role' => [
+        'rules_user_has_role',
+        'User has role',
+        ['context[user][setting]' => 'someone', 'context[roles][setting][]' => 'authenticated'],
+        ['operation' => 'AND'],
+      ],
+      'User is blocked' => [
+        'rules_user_is_blocked',
+        'User is blocked',
+        ['context[user][setting]' => 'someone'],
+      ],
+    ];
+  }
+
+  /**
+   * Test to add each action provided by Rules.
+   *
+   * @param string $id
+   *   The id of the action.
+   * @param string $label
+   *   The label of the acition.
+   * @param array $required
+   *   Array of fields to fill. The key is form field name and the value is the
+   *   text to fill into the field. This should hold just the fields which are
+   *   required and do not have any default value. Use an empty array if there
+   *   are no fields or all fields have a default.
+   * @param array $defaults
+   *   Array of defaults which should be stored without having to select the
+   *   value in the form.
+   *
+   * @dataProvider dataAddActions()
+   */
+  public function testAddActions($id, $label, array $required = [], array $defaults = []) {
+    $agr = print_r($this->account->getRoles(), TRUE);
+    $urn = print_r(user_role_names(TRUE), TRUE);
+    $this->createRule('Add action ' . $id, 'test_rule', 'rules_entity_presave:node', "Add condition $label id=$id\naccount->getRoles() = " . $agr . "\nuser_role_names = " . $urn);
+    $this->clickLink('Add action');
+    $this->fillField('Action', $id);
+    $this->pressButton('Continue');
+
+    // Save the form. If $required is not empty then we should get error(s) so
+    // verify this, then fill in the specified fileds and try to save again.
+    $this->pressButton('Save');
+    if (!empty($required)) {
+      // Check that an error message is shown.
+      $this->assertSession()->pageTextContains('Error message');
+      // Fill in the required fields.
+      foreach ($required as $field => $value) {
+        $this->fillField($field, $value);
+      }
+      $this->pressButton('Save');
+    }
+
+    // Assert that the rule has saved correctly with no error message.
+    $this->assertSession()->pageTextNotContains('Error message');
+    $this->assertSession()->pageTextContains('Edit reaction rule "Add action ' . $id . '"');
+    $this->assertSession()->pageTextContains('Action: ' . $label);
+    // @todo - check that all values ($required and $defaults) have been stored.
+  }
+
+  /**
+   * Provides data for testAddActions().
+   *
+   * @return array
+   *   The test data.
+   */
+  public function dataAddActions() {
+    return [
+
+    /* rules_ban_ip fails interactively and in tests with same error:
+         You have requested a non-existent service "ban.ip_manager
+       'Ban ip address' => [
+        'rules_ban_ip',
+        'Ban IP',
+      ],
+     */
+
+    /* rules_entity_create:comment fails interactively and in tests with error:
+       PluginNotFoundException: The "entity:comment:x" plugin does not exist.
+       All values fails.
+      'Add Comment' => [
+        'rules_entity_create:comment',
+        'Create Comment',
+        ['context[comment_type][setting]' => 'x',
+         'context[entity_id][setting]' => '5']
+      ],
+     */
+      // Content.
+      'Add node' => [
+        'rules_entity_create:node',
+        'Create a new content',
+        ['context[type][setting]' => 'article', 'context[title][setting]' => 'Cakes'],
+      ],
+      // System.
+      'Display system message' => [
+        'rules_system_message',
+        'Show a message on the site',
+        ['context[message][setting]' => 'Here is the news', 'context[type][setting]' => 'status'],
+        ['context[repeat][setting]' => 'no'],
+      ],
+      // User.
+      'User - Add Role' => [
+        'rules_user_role_add',
+        'Add user role',
+        ['context[user][setting]' => 'someone', 'context[roles][setting][]' => 'authenticated'],
+      ],
+      'User - Block' => [
+        'rules_user_block',
+        'Block a user',
+        ['context[user][setting]' => 'someone'],
+      ],
+      'User - Remove Role' => [
+        'rules_user_role_remove',
+        'Remove user role',
+        ['context[user][setting]' => 'someone', 'context[roles][setting][]' => 'authenticated'],
+      ],
+
+    ];
+  }
+
 }
