diff --git a/composer.json b/composer.json
index 16d38b0d150532a17623cba908af0f949d6cf4f8..347eb1dd44c819b23496d43c73f79e672734ebcf 100644
--- a/composer.json
+++ b/composer.json
@@ -184,7 +184,7 @@
         "drupal/views_ajax_history": "1.5",
         "drupal/views_autocomplete_filters": "1.3",
         "drupal/views_bootstrap": "3.1",
-        "drupal/views_bulk_operations": "3.10",
+        "drupal/views_bulk_operations": "3.11",
         "drupal/views_fieldsets": "3.3",
         "drupal/views_infinite_scroll": "1.7",
         "drupal/views_slideshow": "4.4",
diff --git a/composer.lock b/composer.lock
index 24c83e01f3237d1d6c70dd813c2339f864bbb508..1569962c9e32ee65c617f65df893f52851f8a129 100644
--- a/composer.lock
+++ b/composer.lock
@@ -8521,17 +8521,17 @@
         },
         {
             "name": "drupal/views_bulk_operations",
-            "version": "3.10.0",
+            "version": "3.11.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/views_bulk_operations.git",
-                "reference": "8.x-3.10"
+                "reference": "8.x-3.11"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/views_bulk_operations-8.x-3.10.zip",
-                "reference": "8.x-3.10",
-                "shasum": "e346c2a72fc9a1ae8af418e6a02076f52c0fcc7b"
+                "url": "https://ftp.drupal.org/files/projects/views_bulk_operations-8.x-3.11.zip",
+                "reference": "8.x-3.11",
+                "shasum": "14519811dac1661957066a0de6c455228e634ce7"
             },
             "require": {
                 "drupal/core": "^8.8 || ^9"
@@ -8545,8 +8545,8 @@
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-3.10",
-                    "datestamp": "1608795018",
+                    "version": "8.x-3.11",
+                    "datestamp": "1615996407",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
diff --git a/web/modules/views_bulk_operations/js/frontUi.js b/web/modules/views_bulk_operations/js/frontUi.js
index 82013da155ed4deef854abd508b30ae0153846f8..c48e4428c077001e1eeea77a14a05450ef38ce87 100644
--- a/web/modules/views_bulk_operations/js/frontUi.js
+++ b/web/modules/views_bulk_operations/js/frontUi.js
@@ -86,7 +86,9 @@
         }
 
         var $placeholder = this.$placeholder;
+        var $selectionInfo = this.$selectionInfo;
         var target_uri = drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + 'views-bulk-operations/ajax/' + this.view_id + '/' + this.display_id;
+
         $.ajax(target_uri, {
           method: 'POST',
           data: {
@@ -94,6 +96,7 @@
             op: op
           },
           success: function (data) {
+            $selectionInfo.html($(data.selection_info).html());
             $placeholder.text(data.count);
           }
         });
@@ -122,6 +125,7 @@
     var $multiSelectElement = $vboForm.find('.vbo-multipage-selector').first();
     if ($multiSelectElement.length) {
 
+      Drupal.viewsBulkOperationsSelection.$selectionInfo = $multiSelectElement.find('.vbo-info-list-wrapper').first();
       Drupal.viewsBulkOperationsSelection.$placeholder = $multiSelectElement.find('.placeholder').first();
       Drupal.viewsBulkOperationsSelection.view_id = $multiSelectElement.attr('data-view-id');
       Drupal.viewsBulkOperationsSelection.display_id = $multiSelectElement.attr('data-display-id');
@@ -162,9 +166,22 @@
     if ($primarySelectAll.length) {
       $primarySelectAll.on('change', function (event) {
         var value = this.checked;
+
         // Select / deselect all checkboxes in the view.
+        // If there are table select all elements, use that.
+        if (tableSelectAll.length) {
+          tableSelectAll.forEach(function (element) {
+            if (element.get(0).checked != value) {
+              element.click();
+            }
+          });
+        }
+
+        // Also handle checkboxes that may still have different values.
         $vboForm.find('.views-field-views-bulk-operations-bulk-form input[type="checkbox"]').each(function () {
-          this.checked = value;
+          if (this.checked != value) {
+            $(this).click();
+          }
         });
 
         // Clear the selection information if exists.
diff --git a/web/modules/views_bulk_operations/modules/actions_permissions/actions_permissions.info.yml b/web/modules/views_bulk_operations/modules/actions_permissions/actions_permissions.info.yml
index 3b5675c624840a62212724f42cff8e6be452c8b1..27a68f8f1f00ad357f9e86edc97dd949d0d3fbe4 100644
--- a/web/modules/views_bulk_operations/modules/actions_permissions/actions_permissions.info.yml
+++ b/web/modules/views_bulk_operations/modules/actions_permissions/actions_permissions.info.yml
@@ -6,7 +6,7 @@ core_version_requirement: ^8 || ^9
 dependencies:
   - drupal:views_bulk_operations
 
-# Information added by Drupal.org packaging script on 2020-12-24
-version: '8.x-3.10'
+# Information added by Drupal.org packaging script on 2021-03-17
+version: '8.x-3.11'
 project: 'views_bulk_operations'
-datestamp: 1608795021
+datestamp: 1615996410
diff --git a/web/modules/views_bulk_operations/modules/views_bulk_operations_example/views_bulk_operations_example.info.yml b/web/modules/views_bulk_operations/modules/views_bulk_operations_example/views_bulk_operations_example.info.yml
index 2d2965100fc775258329b7ff2eae5911bf5a18de..7b4dfeb407847317bb465e299f4e1607013ef79c 100644
--- a/web/modules/views_bulk_operations/modules/views_bulk_operations_example/views_bulk_operations_example.info.yml
+++ b/web/modules/views_bulk_operations/modules/views_bulk_operations_example/views_bulk_operations_example.info.yml
@@ -6,7 +6,7 @@ core_version_requirement: ^8 || ^9
 dependencies:
   - drupal:views_bulk_operations
 
-# Information added by Drupal.org packaging script on 2020-12-24
-version: '8.x-3.10'
+# Information added by Drupal.org packaging script on 2021-03-17
+version: '8.x-3.11'
 project: 'views_bulk_operations'
-datestamp: 1608795021
+datestamp: 1615996410
diff --git a/web/modules/views_bulk_operations/src/Commands/ViewsBulkOperationsCommands.php b/web/modules/views_bulk_operations/src/Commands/ViewsBulkOperationsCommands.php
index 643ccdce938d0e85a69ad76d625d3b81173c8d2a..523557289501aebfa954dcd49b7a54aa0b97d00d 100644
--- a/web/modules/views_bulk_operations/src/Commands/ViewsBulkOperationsCommands.php
+++ b/web/modules/views_bulk_operations/src/Commands/ViewsBulkOperationsCommands.php
@@ -103,7 +103,7 @@ public function vboExecute(
       'display-id' => 'default',
       'args' => '',
       'exposed' => '',
-      'batch-size' => 100,
+      'batch-size' => 10,
       'configuration' => '',
       'user-id' => 1,
     ]
@@ -144,6 +144,9 @@ public function vboExecute(
       'exposed_input' => $options['exposed'],
       'batch_size' => $options['batch-size'],
       'relationship_id' => 'none',
+      // We set the clear_on_exposed parameter to true, otherwise with empty
+      // selection exposed filters are not taken into account.
+      'clear_on_exposed' => TRUE,
     ];
 
     // Login as superuser, as drush 9 doesn't support the
@@ -179,7 +182,7 @@ public function vboExecute(
 
     // Get total rows count.
     $this->viewData->init($view, $view->getDisplay(), $vbo_data['relationship_id']);
-    $vbo_data['total_results'] = $this->viewData->getTotalResults();
+    $vbo_data['total_results'] = $this->viewData->getTotalResults($vbo_data['clear_on_exposed']);
 
     // Get action definition and check if action ID is correct.
     $action_definition = $this->actionManager->getDefinition($action_id);
diff --git a/web/modules/views_bulk_operations/src/Controller/ViewsBulkOperationsController.php b/web/modules/views_bulk_operations/src/Controller/ViewsBulkOperationsController.php
index 3020241cd3ce49f64417b89084239b5d1c6d34ce..ef00fe3599dcf1b5c6c501116918a16977cb3013 100644
--- a/web/modules/views_bulk_operations/src/Controller/ViewsBulkOperationsController.php
+++ b/web/modules/views_bulk_operations/src/Controller/ViewsBulkOperationsController.php
@@ -8,6 +8,7 @@
 use Drupal\views_bulk_operations\Form\ViewsBulkOperationsFormTrait;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessorInterface;
+use Drupal\Core\Render\RendererInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
@@ -34,6 +35,13 @@ class ViewsBulkOperationsController extends ControllerBase implements ContainerI
    */
   protected $actionProcessor;
 
+  /**
+   * The Renderer service object.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected $renderer;
+
   /**
    * Constructs a new controller object.
    *
@@ -41,13 +49,17 @@ class ViewsBulkOperationsController extends ControllerBase implements ContainerI
    *   Private temporary storage factory.
    * @param \Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessorInterface $actionProcessor
    *   Views Bulk Operations action processor.
+   * @param \Drupal\Core\Render\RendererInterface $renderer
+   *   The Renderer service object.
    */
   public function __construct(
     PrivateTempStoreFactory $tempStoreFactory,
-    ViewsBulkOperationsActionProcessorInterface $actionProcessor
+    ViewsBulkOperationsActionProcessorInterface $actionProcessor,
+    RendererInterface $renderer
   ) {
     $this->tempStoreFactory = $tempStoreFactory;
     $this->actionProcessor = $actionProcessor;
+    $this->renderer = $renderer;
   }
 
   /**
@@ -56,7 +68,8 @@ public function __construct(
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('tempstore.private'),
-      $container->get('views_bulk_operations.processor')
+      $container->get('views_bulk_operations.processor'),
+      $container->get('renderer')
     );
   }
 
@@ -95,8 +108,9 @@ public function execute($view_id, $display_id) {
    *   The request object.
    */
   public function updateSelection($view_id, $display_id, Request $request) {
-    $view_data = $this->getTempstoreData($view_id, $display_id);
-    if (empty($view_data)) {
+    $response = [];
+    $tempstore_data = $this->getTempstoreData($view_id, $display_id);
+    if (empty($tempstore_data)) {
       throw new NotFoundHttpException();
     }
 
@@ -104,7 +118,7 @@ public function updateSelection($view_id, $display_id, Request $request) {
 
     $op = $request->request->get('op', 'check');
     // Reverse operation when in exclude mode.
-    if (!empty($view_data['exclude_mode'])) {
+    if (!empty($tempstore_data['exclude_mode'])) {
       if ($op === 'add') {
         $op = 'remove';
       }
@@ -116,37 +130,43 @@ public function updateSelection($view_id, $display_id, Request $request) {
     switch ($op) {
       case 'add':
         foreach ($list as $bulkFormKey) {
-          if (!isset($view_data['list'][$bulkFormKey])) {
-            $view_data['list'][$bulkFormKey] = $this->getListItem($bulkFormKey);
+          if (!isset($tempstore_data['list'][$bulkFormKey])) {
+            $tempstore_data['list'][$bulkFormKey] = $this->getListItem($bulkFormKey);
           }
         }
         break;
 
       case 'remove':
         foreach ($list as $bulkFormKey) {
-          if (isset($view_data['list'][$bulkFormKey])) {
-            unset($view_data['list'][$bulkFormKey]);
+          if (isset($tempstore_data['list'][$bulkFormKey])) {
+            unset($tempstore_data['list'][$bulkFormKey]);
           }
         }
         break;
 
       case 'method_include':
-        unset($view_data['exclude_mode']);
-        $view_data['list'] = [];
+        unset($tempstore_data['exclude_mode']);
+        $tempstore_data['list'] = [];
         break;
 
       case 'method_exclude':
-        $view_data['exclude_mode'] = TRUE;
-        $view_data['list'] = [];
+        $tempstore_data['exclude_mode'] = TRUE;
+        $tempstore_data['list'] = [];
         break;
     }
 
-    $this->setTempstoreData($view_data);
+    $this->setTempstoreData($tempstore_data);
+
+    $count = empty($tempstore_data['exclude_mode']) ? count($tempstore_data['list']) : $tempstore_data['total_results'] - count($tempstore_data['list']);
 
-    $count = empty($view_data['exclude_mode']) ? count($view_data['list']) : $view_data['total_results'] - count($view_data['list']);
+    $selection_info_renderable = $this->getMultipageList($tempstore_data);
+    $response_data = [
+      'count' => $count,
+      'selection_info' => $this->renderer->renderRoot($selection_info_renderable),
+    ];
 
     $response = new AjaxResponse();
-    $response->setData(['count' => $count]);
+    $response->setData($response_data);
     return $response;
   }
 
diff --git a/web/modules/views_bulk_operations/src/Form/ConfigureAction.php b/web/modules/views_bulk_operations/src/Form/ConfigureAction.php
index a5d4972b2f3def700dd5b6dd98de650413e445d7..a5469c4ba3646b5ffec1de694c913ce4efb7d431 100644
--- a/web/modules/views_bulk_operations/src/Form/ConfigureAction.php
+++ b/web/modules/views_bulk_operations/src/Form/ConfigureAction.php
@@ -143,12 +143,11 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       $form_data['configuration'] = $form_state->getValues();
     }
 
-    $definition = $this->actionManager->getDefinition($form_data['action_id']);
-    if (!empty($definition['confirm_form_route_name'])) {
+    if (!empty($form_data['confirm_route'])) {
       // Update tempStore data.
       $this->setTempstoreData($form_data, $form_data['view_id'], $form_data['display_id']);
       // Go to the confirm route.
-      $form_state->setRedirect($definition['confirm_form_route_name'], [
+      $form_state->setRedirect($form_data['confirm_route'], [
         'view_id' => $form_data['view_id'],
         'display_id' => $form_data['display_id'],
       ]);
diff --git a/web/modules/views_bulk_operations/src/Form/ViewsBulkOperationsFormTrait.php b/web/modules/views_bulk_operations/src/Form/ViewsBulkOperationsFormTrait.php
index 5fe4260896908a5cfb0f4c21daac2267df09ae2a..01bfbbe3ed713e10a9210c7cb4eb673d57fe6ea5 100644
--- a/web/modules/views_bulk_operations/src/Form/ViewsBulkOperationsFormTrait.php
+++ b/web/modules/views_bulk_operations/src/Form/ViewsBulkOperationsFormTrait.php
@@ -70,6 +70,37 @@ protected function addListData(&$form_data) {
     }
   }
 
+  /**
+   * Get the selection info title.
+   *
+   * @param array $tempstore_data
+   *   VBO tempstore data array.
+   *
+   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
+   *   The selection info title.
+   */
+  protected function getSelectionInfoTitle(array $tempstore_data) {
+    if (!empty($tempstore_data['list'])) {
+      return empty($tempstore_data['exclude_mode']) ? $this->t('Items selected:') : $this->t('Selected all items except:');
+    }
+    return $this->t('');
+  }
+
+  /**
+   * Build the selection info element.
+   *
+   * @param array $tempstore_data
+   *   VBO tempstore data array.
+   *
+   * @return array
+   *   Renderable array of the item list.
+   */
+  protected function getMultipageList(array $tempstore_data) {
+    $this->addListData($tempstore_data);
+    $list = $this->getListRenderable($tempstore_data);
+    return $list;
+  }
+
   /**
    * Build selected entities list renderable.
    *
@@ -80,11 +111,12 @@ protected function addListData(&$form_data) {
    *   Renderable list array.
    */
   protected function getListRenderable(array $form_data) {
+    $renderable = [
+      '#theme' => 'item_list',
+      '#items' => $form_data['entity_labels'],
+      '#empty' => $this->t(''),
+    ];
     if (!empty($form_data['entity_labels'])) {
-      $renderable = [
-        '#theme' => 'item_list',
-        '#items' => $form_data['entity_labels'],
-      ];
       $more = count($form_data['list']) - count($form_data['entity_labels']);
       if ($more > 0) {
         $renderable['#items'][] = [
@@ -95,19 +127,11 @@ protected function getListRenderable(array $form_data) {
         ];
       }
     }
-    else {
-      $renderable = [
-        '#type' => 'item',
-        '#markup' => $this->t('All view results'),
-      ];
-    }
-    if (!empty($form_data['exclude_mode'])) {
-      $renderable['#title'] = $this->t('Selected @count entities - all in the view except:', ['@count' => $form_data['selected_count']]);
-    }
-    else {
-      $renderable['#title'] = $this->t('Selected @count entities:', ['@count' => $form_data['selected_count']]);
+    elseif (!empty($form_data['exclude_mode'])) {
+      $renderable['#empty'] = $this->t('All items');
     }
 
+    $renderable['#title'] = $this->getSelectionInfoTitle($form_data);
     $renderable['#wrapper_attributes'] = ['class' => ['vbo-info-list-wrapper']];
 
     return $renderable;
@@ -149,7 +173,7 @@ public static function calculateEntityBulkFormKey(EntityInterface $entity, $base
   }
 
   /**
-   * Get an entity list item from a bulk form key and label.
+   * Get an entity list item from a bulk form key.
    *
    * @param string $bulkFormKey
    *   A bulk form key.
diff --git a/web/modules/views_bulk_operations/src/Plugin/views/field/ViewsBulkOperationsBulkForm.php b/web/modules/views_bulk_operations/src/Plugin/views/field/ViewsBulkOperationsBulkForm.php
index 1f1f00d7bd68f8b880d478ee7c366727e6ae79c0..defcf2144720e5f3ff8f7a2e33f9bc97988bc619 100644
--- a/web/modules/views_bulk_operations/src/Plugin/views/field/ViewsBulkOperationsBulkForm.php
+++ b/web/modules/views_bulk_operations/src/Plugin/views/field/ViewsBulkOperationsBulkForm.php
@@ -215,8 +215,9 @@ protected function updateTempstoreData(array $bulk_form_keys = NULL) {
       'batch' => $this->options['batch'],
       'batch_size' => $this->options['batch'] ? $this->options['batch_size'] : 0,
       'total_results' => $this->viewData->getTotalResults($this->options['clear_on_exposed']),
+      'relationship_id' => $this->options['relationship'],
       'arguments' => $this->view->args,
-      'exposed_input' => $this->view->getExposedInput(),
+      'exposed_input' => $this->getExposedInput(),
     ];
 
     // Add bulk form keys when the form is displayed.
@@ -224,12 +225,6 @@ protected function updateTempstoreData(array $bulk_form_keys = NULL) {
       $variable['bulk_form_keys'] = $bulk_form_keys;
     }
 
-    // A fix to account for empty initial exposed input vs the default values
-    // difference.
-    if (empty($variable['exposed_input'])) {
-      $variable['exposed_input'] = $this->view->exposed_raw_input;
-    }
-
     // Set redirect URL taking destination into account.
     $request = $this->requestStack->getCurrentRequest();
     $destination = $request->query->get('destination');
@@ -287,6 +282,7 @@ protected function updateTempstoreData(array $bulk_form_keys = NULL) {
         if ($variable[$trigger] !== $this->tempStoreData[$trigger]) {
           $this->tempStoreData[$trigger] = $variable[$trigger];
           $this->tempStoreData['list'] = [];
+          $this->tempStoreData['exclude_mode'] = FALSE;
         }
         unset($variable[$trigger]);
         $update = TRUE;
@@ -306,6 +302,33 @@ protected function updateTempstoreData(array $bulk_form_keys = NULL) {
 
   }
 
+  /**
+   * Gets exposed input values from the view.
+   *
+   * @param array $exposed_input
+   *   Current values of exposed input.
+   *
+   * @return array
+   *   Exposed input sorted by filter names.
+   */
+  protected function getExposedInput(array $exposed_input = []) {
+    if (empty($exposed_input)) {
+      // To avoid unnecessary reset of selection, we apply default values. We do
+      // that, because default values can be provided or not in the request, and
+      // it doesn't change results.
+      $exposed_input = array_merge($this->view->getExposedInput(), $this->view->exposed_raw_input);
+    }
+    // Sort values to avoid problems when comparing old and current exposed
+    // input.
+    ksort($exposed_input);
+    foreach ($exposed_input as $name => $value) {
+      if (is_array($value)) {
+        $exposed_input[$name] = $this->getExposedInput($value);
+      }
+    }
+    return $exposed_input;
+  }
+
   /**
    * Gets the current user.
    *
@@ -364,6 +387,7 @@ protected function defineOptions() {
     $options['clear_on_exposed'] = ['default' => TRUE];
     $options['action_title'] = ['default' => $this->t('Action')];
     $options['selected_actions'] = ['default' => []];
+    $options['force_selection_info'] = ['default' => FALSE];
     return $options;
   }
 
@@ -423,6 +447,13 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
       '#default_value' => $this->options['clear_on_exposed'],
     ];
 
+    $form['force_selection_info'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Always show selection info'),
+      '#default_value' => $this->options['force_selection_info'],
+      '#description' => $this->t('Should the selection info fieldset be shown above the view even if there is only one page of results and full selection can be seen in the view itself?'),
+    ];
+
     $form['action_title'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Action title'),
@@ -487,6 +518,16 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         '#default_value' => isset($selected_actions_data[$id]['preconfiguration']['label_override']) ? $selected_actions_data[$id]['preconfiguration']['label_override'] : '',
       ];
 
+      // Also allow to force a default confirmation step for actoins that don't
+      // have it implemented.
+      if (empty($action['confirm_form_route_name'])) {
+        $form['selected_actions'][$delta]['preconfiguration']['add_confirmation'] = [
+          '#type' => 'checkbox',
+          '#title' => $this->t('Add confirmation step'),
+          '#default_value' => isset($selected_actions_data[$id]['preconfiguration']['add_confirmation']) ? $selected_actions_data[$id]['preconfiguration']['add_confirmation'] : FALSE,
+        ];
+      }
+
       // Load preconfiguration form if available.
       if (method_exists($action['class'], 'buildPreConfigurationForm')) {
         if (!isset($selected_actions_data[$id]['preconfiguration'])) {
@@ -588,15 +629,18 @@ public function viewsForm(array &$form, FormStateInterface $form_state) {
     $action_options = $this->getBulkOptions();
     if (!empty($this->view->result) && !empty($action_options)) {
 
-      // Calculate bulk form keys for all rows.
+      // Calculate bulk form keys and get labels for all rows.
       $bulk_form_keys = [];
+      $entity_labels = [];
       $base_field = $this->view->storage->get('base_field');
       foreach ($this->view->result as $row_index => $row) {
-        $entity = $this->getEntity($row);
-        $bulk_form_keys[$row_index] = self::calculateEntityBulkFormKey(
-          $entity,
-          $row->{$base_field}
-        );
+        if ($entity = $this->getEntity($row)) {
+          $bulk_form_keys[$row_index] = self::calculateEntityBulkFormKey(
+            $entity,
+            $row->{$base_field}
+          );
+          $entity_labels[$row_index] = $entity->label();
+        }
       }
 
       // Update and fetch tempstore data to be available from this point
@@ -624,8 +668,7 @@ public function viewsForm(array &$form, FormStateInterface $form_state) {
 
       // Render checkboxes for all rows.
       $page_selected = [];
-      foreach ($this->view->result as $row_index => $row) {
-        $bulk_form_key = $bulk_form_keys[$row_index];
+      foreach ($bulk_form_keys as $row_index => $bulk_form_key) {
         $checked = isset($this->tempStoreData['list'][$bulk_form_key]);
         if (!empty($this->tempStoreData['exclude_mode'])) {
           $checked = !$checked;
@@ -636,7 +679,7 @@ public function viewsForm(array &$form, FormStateInterface $form_state) {
         }
         $form[$this->options['id']][$row_index] = [
           '#type' => 'checkbox',
-          '#title' => $entity->label(),
+          '#title' => $entity_labels[$row_index],
           '#title_display' => 'invisible',
           '#default_value' => $checked,
           '#return_value' => $bulk_form_key,
@@ -711,23 +754,28 @@ public function viewsForm(array &$form, FormStateInterface $form_state) {
         }
       }
 
-      $display_select_all = (
-        !$this->options['clear_on_exposed'] &&
-        !empty($this->view->getExposedInput())
-      ) ||
-      (
-        isset($pagerData) &&
-        (
-          $pagerData['more'] ||
-          $pagerData['current'] > 0
-        )
-      );
-
       // Selection info: displayed if exposed filters are set and selection
       // is not cleared when they change or "select all" element display
-      // conditions are met.
-      if ($display_select_all) {
+      // conditions are met. Also displayed by default if VBO field has such
+      // configuration set.
+      if ($this->options['force_selection_info']) {
+        $display_select_all = TRUE;
+      }
+      else {
+        $display_select_all = (
+          !$this->options['clear_on_exposed'] &&
+          !empty($this->view->getExposedInput())
+        ) ||
+        (
+          isset($pagerData) &&
+          (
+            $pagerData['more'] ||
+            $pagerData['current'] > 0
+          )
+        );
+      }
 
+      if ($display_select_all) {
         $count = empty($this->tempStoreData['exclude_mode']) ? count($this->tempStoreData['list']) : $this->tempStoreData['total_results'] - count($this->tempStoreData['list']);
         $form['header'][$this->options['id']]['multipage'] = [
           '#type' => 'details',
@@ -741,27 +789,11 @@ public function viewsForm(array &$form, FormStateInterface $form_state) {
             'data-view-id' => $this->tempStoreData['view_id'],
             'data-display-id' => $this->tempStoreData['display_id'],
             'class' => ['vbo-multipage-selector'],
-            'name' => 'somename',
           ],
         ];
 
-        // Display a list of items selected on other pages.
-        if ($count > count($page_selected)) {
-          $form_data = $this->tempStoreData;
-          $form_data['list'] = [];
-          $form_data['relationship_id'] = $this->options['relationship'];
-          foreach ($this->tempStoreData['list'] as $bulk_form_key => $item) {
-            if (!in_array($bulk_form_key, $page_selected)) {
-              $form_data['list'][$bulk_form_key] = $item;
-            }
-          }
-          $this->addListData($form_data);
-          $form['header'][$this->options['id']]['multipage']['list'] = $this->getListRenderable($form_data);
-          $form['header'][$this->options['id']]['multipage']['list']['#title'] = empty($this->tempStoreData['exclude_mode']) ? $this->t('Items selected on other pages:') : $this->t('Items excluded on other pages:');
-          $form['header'][$this->options['id']]['multipage']['list']['#empty'] = $this->t('No selection');
-
-        }
-
+        // Get selection info elements.
+        $form['header'][$this->options['id']]['multipage']['list'] = $this->getMultipageList($this->tempStoreData);
         $form['header'][$this->options['id']]['multipage']['clear'] = [
           '#type' => 'submit',
           '#value' => $this->t('Clear'),
@@ -862,6 +894,10 @@ public function viewsFormSubmit(array &$form, FormStateInterface $form_state) {
       $this->tempStoreData['relationship_id'] = $this->options['relationship'];
       $this->tempStoreData['preconfiguration'] = isset($action_config['preconfiguration']) ? $action_config['preconfiguration'] : [];
       $this->tempStoreData['clear_on_exposed'] = $this->options['clear_on_exposed'];
+      $this->tempStoreData['confirm_route'] = $action['confirm_form_route_name'];
+      if (empty($this->tempStoreData['confirm_route']) && !empty($action_config['preconfiguration']['add_confirmation'])) {
+        $this->tempStoreData['confirm_route'] = 'views_bulk_operations.confirm';
+      }
 
       $configurable = $this->isActionConfigurable($action);
 
@@ -915,13 +951,8 @@ public function viewsFormSubmit(array &$form, FormStateInterface $form_state) {
       if ($this->options['form_step'] && $configurable) {
         $redirect_route = 'views_bulk_operations.execute_configurable';
       }
-      elseif ($this->options['batch']) {
-        if (!empty($action['confirm_form_route_name'])) {
-          $redirect_route = $action['confirm_form_route_name'];
-        }
-      }
-      elseif (!empty($action['confirm_form_route_name'])) {
-        $redirect_route = $action['confirm_form_route_name'];
+      elseif (!empty($this->tempStoreData['confirm_route'])) {
+        $redirect_route = $this->tempStoreData['confirm_route'];
       }
 
       // Redirect if needed.
diff --git a/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsActionManager.php b/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsActionManager.php
index 00db7e5153e28cc0165d5dd0fa85ec6bb5783566..1a0bdb3752909c4a4b1ebbd8ef269ece17de45a4 100644
--- a/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsActionManager.php
+++ b/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsActionManager.php
@@ -79,8 +79,6 @@ protected function findDefinitions() {
 
     $entity_type_definitions = $this->entityTypeManager->getDefinitions();
     foreach ($definitions as $plugin_id => &$definition) {
-      $this->processDefinition($definition, $plugin_id);
-
       // We only allow actions of existing entity type and empty
       // type meaning it's applicable to all entity types.
       if (
@@ -96,11 +94,21 @@ protected function findDefinitions() {
       // Filter definitions that are incompatible due to applied core
       // configuration form workaround (using confirm_form_route for config
       // forms and using action execute() method for purposes other than
-      // actual action execution). Luckily, core also has useful actions
-      // without the workaround, like node_assign_owner_action.
-      if (!in_array('Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionInterface', class_implements($definition['class'])) && (!empty($definition['confirm_form_route_name']))) {
-        unset($definitions[$plugin_id]);
+      // actual action execution). Also filter out actions that don't implement
+      // ViewsBulkOperationsActionInterface and have empty type as this
+      // shouldn't be the case in core. Luckily, core also has useful actions
+      // without the workaround, like node_assign_owner_action or
+      // comment_unpublish_by_keyword_action.
+      if (!in_array('Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionInterface', class_implements($definition['class']))) {
+        if (
+          !empty($definition['confirm_form_route_name']) ||
+          empty($definition['type'])
+        ) {
+          unset($definitions[$plugin_id]);
+        }
       }
+
+      $this->processDefinition($definition, $plugin_id);
     }
     $this->alterDefinitions($definitions);
     foreach ($definitions as $plugin_id => $plugin_definition) {
diff --git a/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsViewData.php b/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsViewData.php
index a3466f4b340387cc65ca05074d98751e6b06cee2..00f2e3f6e2c771c62df2317b69c021080eb7ca9a 100644
--- a/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsViewData.php
+++ b/web/modules/views_bulk_operations/src/Service/ViewsBulkOperationsViewData.php
@@ -243,6 +243,10 @@ public function getEntityDefault(ResultRow $row, $relationship_id, ViewExecutabl
       throw new \Exception('Unexpected view result row structure.');
     }
 
+    if (empty($entity)) {
+      return;
+    }
+
     if ($entity instanceof TranslatableInterface && $entity->isTranslatable()) {
 
       // Try to find a field alias for the langcode.
diff --git a/web/modules/views_bulk_operations/tests/src/Functional/DrushCommandsTest.php b/web/modules/views_bulk_operations/tests/src/Functional/DrushCommandsTest.php
index 91a86b3b59ef8bb6b57e950609e9e113f09d13f1..67241da11baf697cb2ca36564c2418d18bc5a86c 100644
--- a/web/modules/views_bulk_operations/tests/src/Functional/DrushCommandsTest.php
+++ b/web/modules/views_bulk_operations/tests/src/Functional/DrushCommandsTest.php
@@ -49,7 +49,7 @@ protected function setUp() {
       $this->testNodes[] = $this->drupalCreateNode([
         'type' => 'page',
         'title' => 'Title ' . $i,
-        'sticky' => FALSE,
+        'sticky' => $i % 2 ? TRUE : FALSE,
         'created' => $time,
         'changed' => $time,
       ]);
@@ -61,9 +61,23 @@ protected function setUp() {
    * Tests the VBO Drush command.
    */
   public function testDrushCommand() {
+    // Basic test.
     $this->drush('vbo-exec', ['views_bulk_operations_test', 'views_bulk_operations_simple_test_action']);
-    $this->assertStringContainsString('Test action (preconfig: , label: Title 0)', $this->getErrorOutput());
-    $this->assertStringContainsString('Test action (preconfig: , label: Title 14)', $this->getErrorOutput());
+    for ($i = 0; $i < self::TEST_NODE_COUNT; $i++) {
+      $this->assertStringContainsString("Test action (preconfig: , label: Title $i)", $this->getErrorOutput());
+    }
+
+    // Exposed filters test.
+    $this->drush('vbo-exec', ['views_bulk_operations_test', 'views_bulk_operations_simple_test_action'], ['exposed' => 'sticky=1']);
+    for ($i = 0; $i < self::TEST_NODE_COUNT; $i++) {
+      $test_string = "Test action (preconfig: , label: Title $i)";
+      if ($i % 2) {
+        $this->assertStringContainsString($test_string, $this->getErrorOutput());
+      }
+      else {
+        $this->assertStringNotContainsString($test_string, $this->getErrorOutput());
+      }
+    }
   }
 
 }
diff --git a/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsBulkFormTest.php b/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsBulkFormTest.php
index 3c700d685a5ff52159e1102c423f8da2b755ff0f..4a981ef31cd8cdcfe5b1eb636cb209a44a23b5ee 100644
--- a/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsBulkFormTest.php
+++ b/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsBulkFormTest.php
@@ -3,58 +3,12 @@
 namespace Drupal\Tests\views_bulk_operations\Functional;
 
 use Drupal\Component\Render\FormattableMarkup;
-use Drupal\Tests\BrowserTestBase;
 
 /**
  * @coversDefaultClass \Drupal\views_bulk_operations\Plugin\views\field\ViewsBulkOperationsBulkForm
  * @group views_bulk_operations
  */
-class ViewsBulkOperationsBulkFormTest extends BrowserTestBase {
-
-  const TEST_NODE_COUNT = 15;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected $defaultTheme = 'stable';
-
-  /**
-   * Modules to install.
-   *
-   * @var array
-   */
-  public static $modules = [
-    'node',
-    'views',
-    'views_bulk_operations',
-    'views_bulk_operations_test',
-  ];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    // Create some nodes for testing.
-    $this->drupalCreateContentType(['type' => 'page']);
-
-    $this->testNodes = [];
-    $time = $this->container->get('datetime.time')->getRequestTime();
-    for ($i = 0; $i < self::TEST_NODE_COUNT; $i++) {
-      // Ensure nodes are sorted in the same order they are inserted in the
-      // array.
-      $time -= $i;
-      $this->testNodes[] = $this->drupalCreateNode([
-        'type' => 'page',
-        'title' => 'Title ' . $i,
-        'sticky' => FALSE,
-        'created' => $time,
-        'changed' => $time,
-      ]);
-    }
-
-  }
+class ViewsBulkOperationsBulkFormTest extends ViewsBulkOperationsFunctionalTestBase {
 
   /**
    * Tests the VBO bulk form with simple test action.
@@ -69,10 +23,12 @@ public function testViewsBulkOperationsBulkFormSimple() {
     $first_form_element = $this->xpath('//form/div[1][@id = :id]', [':id' => 'edit-header']);
     $this->assertNotEmpty($first_form_element, 'The views form edit header appears first.');
 
-    // Make sure a checkbox appears on all rows.
-    $edit = [];
+    // Make sure a checkbox appears on all rows and every checkbox has
+    // the correct label.
     for ($i = 0; $i < 4; $i++) {
-      $assertSession->fieldExists('edit-views-bulk-operations-bulk-form-' . $i, NULL, new FormattableMarkup('The checkbox on row @row appears.', ['@row' => $i]));
+      $checkbox_selector = 'edit-views-bulk-operations-bulk-form-' . $i;
+      $assertSession->fieldExists($checkbox_selector, NULL, new FormattableMarkup('The checkbox on row @row appears.', ['@row' => $i]));
+      $assertSession->elementTextContains('css', "label[for=$checkbox_selector]", $this->testNodes[$i]->label());
     }
 
     // The advanced action should not be shown on the form - no permission.
@@ -84,14 +40,8 @@ public function testViewsBulkOperationsBulkFormSimple() {
     $this->drupalLogin($admin_user);
 
     // Execute the simple test action.
-    $edit = [];
     $selected = [0, 2, 3];
-    foreach ($selected as $index) {
-      $edit["views_bulk_operations_bulk_form[$index]"] = TRUE;
-    }
-
-    // Tests: actions as buttons, label override.
-    $this->drupalPostForm('views-bulk-operations-test', $edit, t('Simple test action'));
+    $this->executeAction('views-bulk-operations-test', t('Simple test action'), $selected);
 
     $testViewConfig = \Drupal::service('config.factory')->get('views.view.views_bulk_operations_test');
     $configData = $testViewConfig->getRawData();
@@ -110,17 +60,12 @@ public function testViewsBulkOperationsBulkFormSimple() {
     }
 
     // Test the select all functionality.
-    $edit = [
-      'select_all' => 1,
-    ];
     // With the exclude mode, we also have to select all rows of the
     // view, otherwise those will be treated as excluded. In the UI
     // this is handled by JS.
-    foreach ([0, 1, 2, 3] as $index) {
-      $edit["views_bulk_operations_bulk_form[$index]"] = TRUE;
-    }
-
-    $this->drupalPostForm(NULL, $edit, t('Simple test action'));
+    $selected = [0, 1, 2, 3];
+    $data = ['select_all' => 1];
+    $this->executeAction(NULL, t('Simple test action'), $selected, $data);
 
     $assertSession->pageTextContains(
       sprintf('Action processing results: Test (%d).', self::TEST_NODE_COUNT),
@@ -145,14 +90,9 @@ public function testViewsBulkOperationsBulkFormAdvanced() {
 
     // First execute the simple action to test
     // the ViewsBulkOperationsController class.
-    $edit = [
-      'action' => 0,
-    ];
     $selected = [0, 2];
-    foreach ($selected as $index) {
-      $edit["views_bulk_operations_bulk_form[$index]"] = TRUE;
-    }
-    $this->drupalPostForm('views-bulk-operations-test-advanced', $edit, t('Apply to selected items'));
+    $data = ['action' => 0];
+    $this->executeAction('views-bulk-operations-test-advanced', t('Apply to selected items'), $selected, $data);
 
     $assertSession->pageTextContains(
       sprintf('Action processing results: Test (%d).', count($selected)),
@@ -160,14 +100,9 @@ public function testViewsBulkOperationsBulkFormAdvanced() {
     );
 
     // Execute the advanced test action.
-    $edit = [
-      'action' => 1,
-    ];
     $selected = [0, 1, 3];
-    foreach ($selected as $index) {
-      $edit["views_bulk_operations_bulk_form[$index]"] = TRUE;
-    }
-    $this->drupalPostForm('views-bulk-operations-test-advanced', $edit, t('Apply to selected items'));
+    $data = ['action' => 1];
+    $this->executeAction('views-bulk-operations-test-advanced', t('Apply to selected items'), $selected, $data);
 
     // Check if the configuration form is open and contains the
     // test_config field.
@@ -238,7 +173,7 @@ public function testViewsBulkOperationsBulkFormPassing() {
 
     $assertSession = $this->assertSession();
 
-    // Log in as a user with 'administer content' permission
+    // Log in as a user with 'bypass node access' permission
     // to have access to perform the test operation.
     $admin_user = $this->drupalCreateUser(['bypass node access']);
     $this->drupalLogin($admin_user);
@@ -326,4 +261,32 @@ public function testViewsBulkOperationsBulkFormPassing() {
 
   }
 
+  /**
+   * Test core action - specific configuration.
+   */
+  public function testActionCorePreconfig() {
+    $assertSession = $this->assertSession();
+
+    $testViewConfig = \Drupal::service('config.factory')->getEditable('views.view.views_bulk_operations_test');
+    $configData = $testViewConfig->getRawData();
+    $preconfig = &$configData['display']['default']['display_options']['fields']['views_bulk_operations_bulk_form']['selected_actions'][0]['preconfiguration'];
+    $preconfig['add_confirmation'] = TRUE;
+    $testViewConfig->setData($configData);
+    $testViewConfig->save();
+
+    $this->drupalGet('views-bulk-operations-test');
+
+    // Log in as a user with 'edit any page content' permission
+    // to have access to perform the test operation.
+    $admin_user = $this->drupalCreateUser(['edit any page content']);
+    $this->drupalLogin($admin_user);
+
+    // Check if we're on the confirmation form and if the overridden label
+    // is displayed.
+    $selection = [0, 2, 3];
+    $label = $preconfig['label_override'];
+    $this->executeAction('views-bulk-operations-test', t('Simple test action'), $selection);
+    $assertSession->pageTextContains(sprintf('Are you sure you wish to perform "%s" action on %d entities?', $label, count($selection)));
+  }
+
 }
diff --git a/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsFunctionalTestBase.php b/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsFunctionalTestBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..eb7fd6f615a9b125112873ef6d0954ee1b2df8fd
--- /dev/null
+++ b/web/modules/views_bulk_operations/tests/src/Functional/ViewsBulkOperationsFunctionalTestBase.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Drupal\Tests\views_bulk_operations\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Base class for VBO browser tests.
+ */
+abstract class ViewsBulkOperationsFunctionalTestBase extends BrowserTestBase {
+
+  const TEST_NODE_COUNT = 15;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stable';
+
+  /**
+   * Modules to install.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'node',
+    'views',
+    'views_bulk_operations',
+    'views_bulk_operations_test',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // Create some nodes for testing.
+    $this->drupalCreateContentType(['type' => 'page']);
+
+    $this->testNodes = [];
+    $time = $this->container->get('datetime.time')->getRequestTime();
+    for ($i = 0; $i < static::TEST_NODE_COUNT; $i++) {
+      // Ensure nodes are sorted in the same order they are inserted in the
+      // array.
+      $time -= $i;
+      $this->testNodes[] = $this->drupalCreateNode([
+        'type' => 'page',
+        'title' => 'Title ' . $i,
+        'sticky' => FALSE,
+        'created' => $time,
+        'changed' => $time,
+      ]);
+    }
+
+  }
+
+  /**
+   * Helper function that gets configuration for a selected view.
+   *
+   * @param string|null $path
+   *   The path of the View page that includes VBO.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup $button_text
+   *   The form submit button text.
+   * @param int[] $selection
+   *   The selected items' indexes.
+   * @param array $data
+   *   Additional parameters for the submitted form.
+   */
+  protected function executeAction($path, TranslatableMarkup $button_text, array $selection = [], array $data = []) {
+    foreach ($selection as $index) {
+      $data["views_bulk_operations_bulk_form[$index]"] = TRUE;
+    }
+    $this->drupalPostForm($path, $data, $button_text);
+  }
+
+}
diff --git a/web/modules/views_bulk_operations/tests/src/FunctionalJavascript/ViewsBulkOperationsBulkFormTest.php b/web/modules/views_bulk_operations/tests/src/FunctionalJavascript/ViewsBulkOperationsBulkFormTest.php
index 7263470640aa5648322ffbd247c2d5d95206d348..6468565a67d40101ca94b9d0e054993d2fcdc1db 100644
--- a/web/modules/views_bulk_operations/tests/src/FunctionalJavascript/ViewsBulkOperationsBulkFormTest.php
+++ b/web/modules/views_bulk_operations/tests/src/FunctionalJavascript/ViewsBulkOperationsBulkFormTest.php
@@ -15,6 +15,8 @@ class ViewsBulkOperationsBulkFormTest extends WebDriverTestBase {
 
   const TEST_NODE_COUNT = 15;
 
+  const TEST_VIEW_ID = 'views_bulk_operations_test';
+
   /**
    * {@inheritdoc}
    */
@@ -43,6 +45,20 @@ class ViewsBulkOperationsBulkFormTest extends WebDriverTestBase {
    */
   protected $selectedIndexes = [];
 
+  /**
+   * Test nodes.
+   *
+   * @var \Drupal\node\NodeInterface[]
+   */
+  protected $testNodes = [];
+
+  /**
+   * Test view parameters as in the config.
+   *
+   * @var array
+   */
+  protected $testViewParams;
+
   /**
    * Modules to install.
    *
@@ -63,8 +79,8 @@ protected function setUp() {
 
     // Create some nodes for testing.
     $this->drupalCreateContentType(['type' => 'page']);
-    for ($i = 1; $i <= self::TEST_NODE_COUNT; $i++) {
-      $this->drupalCreateNode([
+    for ($i = 0; $i <= self::TEST_NODE_COUNT; $i++) {
+      $node = $this->drupalCreateNode([
         'type' => 'page',
         'title' => 'Title ' . $i,
       ]);
@@ -80,31 +96,52 @@ protected function setUp() {
     $this->assertSession = $this->assertSession();
     $this->page = $this->getSession()->getPage();
 
-    $this->drupalGet('/views-bulk-operations-test');
+    // Get useful config data from the test view.
+    $config_data = \Drupal::service('config.factory')->get('views.view.' . self::TEST_VIEW_ID)->getRawData();
+    $this->testViewParams = [
+      'items_per_page' => $config_data['display']['default']['display_options']['pager']['options']['items_per_page'],
+      'path' => $config_data['display']['page_1']['display_options']['path'],
+    ];
 
+    $this->drupalGet('/' . $this->testViewParams['path']);
+  }
+
+  /**
+   * Tests the VBO bulk form without dynamic insertion.
+   */
+  public function testViewsBulkOperationsAjaxUi() {
     // Make sure a checkbox appears on all rows and the button exists.
-    for ($i = 0; $i < 4; $i++) {
+    $this->assertSession->buttonExists('Simple test action');
+    for ($i = 0; $i < $this->testViewParams['items_per_page']; $i++) {
       $this->assertSession->fieldExists('edit-views-bulk-operations-bulk-form-' . $i);
     }
-    $this->assertSession->buttonExists('Simple test action');
-
-    $this->selectedIndexes = [0, 1, 3];
 
-    foreach ($this->selectedIndexes as $selected_index) {
+    // Select some items on the first page.
+    foreach ([0, 1, 3] as $selected_index) {
+      $this->selectedIndexes[] = $selected_index;
       $this->page->checkField('edit-views-bulk-operations-bulk-form-' . $selected_index);
     }
 
-  }
-
-  /**
-   * Tests the VBO bulk form without dynamic insertion.
-   */
-  public function testViewsBulkOperationsWithOutDynamicInsertion() {
+    // Go to the next page and select some more.
+    $this->page->clickLink('Go to next page');
+    foreach ([1, 2] as $selected_index) {
+      // This is page one so indexes are incremented by page count and
+      // checkbox selectors start from 0 again.
+      $this->selectedIndexes[] = $selected_index + $this->testViewParams['items_per_page'];
+      $this->page->checkField('edit-views-bulk-operations-bulk-form-' . $selected_index);
+    }
 
+    // Execute test operation.
     $this->page->pressButton('Simple test action');
 
-    foreach ($this->selectedIndexes as $index) {
-      $this->assertSession->pageTextContains(sprintf('Test action (preconfig: Test setting, label: Title %s)', self::TEST_NODE_COUNT - $index));
+    // Assert if only the selected nodes were processed.
+    foreach ($this->testNodes as $delta => $node) {
+      if (in_array($delta, $this->selectedIndexes, TRUE)) {
+        $this->assertSession->pageTextContains(sprintf('Test action (preconfig: Test setting, label: %s)', $node->label()));
+      }
+      else {
+        $this->assertSession->pageTextNotContains(sprintf('Test action (preconfig: Test setting, label: %s)', $node->label()));
+      }
     }
     $this->assertSession->pageTextContains(sprintf('Action processing results: Test (%s)', count($this->selectedIndexes)));
 
@@ -117,6 +154,12 @@ public function testViewsBulkOperationsWithOutDynamicInsertion() {
    */
   public function testViewsBulkOperationsWithDynamicInsertion() {
 
+    $this->selectedIndexes = [0, 1, 3];
+
+    foreach ($this->selectedIndexes as $selected_index) {
+      $this->page->checkField('edit-views-bulk-operations-bulk-form-' . $selected_index);
+    }
+
     // Insert nodes.
     $nodes = [];
     for ($i = 100; $i < 100 + self::TEST_NODE_COUNT; $i++) {
@@ -132,12 +175,6 @@ public function testViewsBulkOperationsWithDynamicInsertion() {
       $this->assertSession->pageTextContains(sprintf('Test action (preconfig: Test setting, label: Title %s)', self::TEST_NODE_COUNT - $index));
     }
     $this->assertSession->pageTextContains(sprintf('Action processing results: Test (%s)', count($this->selectedIndexes)));
-
-    // Remove nodes inserted in the middle.
-    foreach ($nodes as $node) {
-      $node->delete();
-    }
-
   }
 
 }
diff --git a/web/modules/views_bulk_operations/tests/views_bulk_operations_test/config/install/views.view.views_bulk_operations_test.yml b/web/modules/views_bulk_operations/tests/views_bulk_operations_test/config/install/views.view.views_bulk_operations_test.yml
index 712b47789d56160130b09f7f54de64ffa8baeb40..96279aa797243c073d39d8da4d123c95bcf2ae78 100644
--- a/web/modules/views_bulk_operations/tests/views_bulk_operations_test/config/install/views.view.views_bulk_operations_test.yml
+++ b/web/modules/views_bulk_operations/tests/views_bulk_operations_test/config/install/views.view.views_bulk_operations_test.yml
@@ -12,7 +12,6 @@ description: ''
 tag: ''
 base_table: node_field_data
 base_field: nid
-core: 8.x
 display:
   default:
     display_plugin: default
@@ -170,17 +169,61 @@ display:
           buttons: true
           action_title: Action
           selected_actions:
-            0:
+            -
               action_id: views_bulk_operations_simple_test_action
               preconfiguration:
                 label_override: 'Simple test action'
                 preconfig: 'Test setting'
-            1:
+            -
               action_id: views_bulk_operations_advanced_test_action
               preconfiguration:
                 preconfig: 'Test setting'
           plugin_id: views_bulk_operations_bulk_form
-      filters: {  }
+      filters:
+        sticky:
+          id: sticky
+          table: node_field_data
+          field: sticky
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: '='
+          value: All
+          group: 1
+          exposed: true
+          expose:
+            operator_id: ''
+            label: 'Sticky status'
+            description: ''
+            use_operator: false
+            operator: sticky_op
+            operator_limit_selection: false
+            operator_list: {  }
+            identifier: sticky
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              administrator: '0'
+              role_1: '0'
+              role_2: '0'
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: node
+          entity_field: sticky
+          plugin_id: boolean
       sorts:
         created:
           id: created
@@ -209,6 +252,7 @@ display:
       contexts:
         - 'languages:language_content'
         - 'languages:language_interface'
+        - url
         - url.query_args
         - 'user.node_grants:view'
         - user.permissions
@@ -226,6 +270,7 @@ display:
       contexts:
         - 'languages:language_content'
         - 'languages:language_interface'
+        - url
         - url.query_args
         - 'user.node_grants:view'
         - user.permissions
diff --git a/web/modules/views_bulk_operations/tests/views_bulk_operations_test/views_bulk_operations_test.info.yml b/web/modules/views_bulk_operations/tests/views_bulk_operations_test/views_bulk_operations_test.info.yml
index 1d3513193f973e4882c9f1e188fbe7a971d8172b..9f14699ee451bea53e0e887ea8a3dc7c9a582a2c 100644
--- a/web/modules/views_bulk_operations/tests/views_bulk_operations_test/views_bulk_operations_test.info.yml
+++ b/web/modules/views_bulk_operations/tests/views_bulk_operations_test/views_bulk_operations_test.info.yml
@@ -7,7 +7,7 @@ dependencies:
   - drupal:views_bulk_operations
   - drupal:node
 
-# Information added by Drupal.org packaging script on 2020-12-24
-version: '8.x-3.10'
+# Information added by Drupal.org packaging script on 2021-03-17
+version: '8.x-3.11'
 project: 'views_bulk_operations'
-datestamp: 1608795021
+datestamp: 1615996410
diff --git a/web/modules/views_bulk_operations/views_bulk_operations.info.yml b/web/modules/views_bulk_operations/views_bulk_operations.info.yml
index 9539dbe95dbe7a65e514e269b8d624345a6303cf..94a11698912b2b134bec2327a7f2c196f2a54aae 100644
--- a/web/modules/views_bulk_operations/views_bulk_operations.info.yml
+++ b/web/modules/views_bulk_operations/views_bulk_operations.info.yml
@@ -6,7 +6,7 @@ core_version_requirement: ^8.8 || ^9
 dependencies:
   - drupal:views
 
-# Information added by Drupal.org packaging script on 2020-12-24
-version: '8.x-3.10'
+# Information added by Drupal.org packaging script on 2021-03-17
+version: '8.x-3.11'
 project: 'views_bulk_operations'
-datestamp: 1608795021
+datestamp: 1615996410