diff --git a/core/modules/contextual/js/toolbar/views/AuralView.js b/core/modules/contextual/js/toolbar/views/AuralView.js
index d684ffb9e6..66fbbd8dcd 100644
--- a/core/modules/contextual/js/toolbar/views/AuralView.js
+++ b/core/modules/contextual/js/toolbar/views/AuralView.js
@@ -55,8 +55,11 @@
       var tabbingContext = this.model.get('tabbingContext');
       // Always release an existing tabbing context.
       if (tabbingContext) {
+        // Only announce release when the context was active.
+        if (tabbingContext.active) {
+          Drupal.announce(this.options.strings.tabbingReleased);
+        }
         tabbingContext.release();
-        Drupal.announce(this.options.strings.tabbingReleased);
       }
       // Create a new tabbing context when edit mode is enabled.
       if (!this.model.get('isViewing')) {
diff --git a/core/modules/contextual/tests/src/FunctionalJavascript/EditModeTest.php b/core/modules/contextual/tests/src/FunctionalJavascript/EditModeTest.php
new file mode 100644
index 0000000000..9fdef448d7
--- /dev/null
+++ b/core/modules/contextual/tests/src/FunctionalJavascript/EditModeTest.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Drupal\Tests\contextual\FunctionalJavascript;
+
+use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
+
+/**
+ * Tests edit mode.
+ *
+ * @group contextual
+ */
+class EditModeTest extends JavascriptTestBase {
+
+  const ANNOUNCE_SELECTOR = '#drupal-live-announce';
+
+  const EDIT_BUTTON_SELECTOR = '#toolbar-bar div.contextual-toolbar-tab button';
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'node',
+    'block',
+    'user',
+    'system',
+    'breakpoint',
+    'toolbar',
+    'contextual',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $user = $this->createUser([
+      'administer blocks',
+      'access contextual links',
+      'access toolbar',
+    ]);
+    $this->drupalLogin($user);
+    $this->placeBlock('system_powered_by_block', ['id' => 'powered']);
+  }
+
+  /**
+   * Test Drupal.announce messages appear.
+   */
+  public function testAnnounceEditMode() {
+    $web_assert = $this->assertSession();
+    $this->drupalGet('user');
+
+    // After the page loaded we need to additionally wait until the settings
+    // tray Ajax activity is done.
+    $web_assert->assertWaitOnAjaxRequest();
+
+    // Enable edit mode.
+    $this->pressToolbarEditButton();
+    $this->assertAnnounceEditMode();
+    // Disable edit mode.
+    $this->pressToolbarEditButton();
+    $this->assertAnnounceLeaveEditMode();
+    // Enable edit mode again.
+    $this->pressToolbarEditButton();
+    // Finally assert that the 'edit mode enabled' announcement is still correct
+    // after toggling the edit mode at least once.
+    $this->assertAnnounceEditMode();
+  }
+
+  /**
+   * Press the toolbar edit mode.
+   */
+  protected function pressToolbarEditButton() {
+    $edit_button = $this->getSession()->getPage()->find('css', static::EDIT_BUTTON_SELECTOR);
+    $edit_button->press();
+  }
+
+  /**
+   * Assert that the correct message was announced when entering edit mode.
+   */
+  protected function assertAnnounceEditMode() {
+    $web_assert = $this->assertSession();
+    // Wait for contextual trigger button.
+    $web_assert->waitForElementVisible('css', '.contextual trigger');
+    $web_assert->elementContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is constrained to a set of');
+    $web_assert->elementNotContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is no longer constrained by the Contextual module.');
+  }
+
+  /**
+   * Assert that the correct message was announced when leaving edit mode.
+   */
+  protected function assertAnnounceLeaveEditMode() {
+    $web_assert = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    // Wait till all the contextual links are hidden.
+    $page->waitFor(1, function () use ($page, $web_assert) {
+      return empty($page->find('css', '.contextual .trigger.visually-hidden'));
+    });
+    $web_assert->elementContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is no longer constrained by the Contextual module.');
+    $web_assert->elementNotContains('css', static::ANNOUNCE_SELECTOR, 'Tabbing is constrained to a set of');
+  }
+
+}
