diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 81fa3f0..82b9d81 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -144,7 +144,7 @@ function node_tokens($type, $tokens, array $data, array $options, BubbleableMeta
                 // Get the 'trim_length' size used for the 'teaser' mode, if
                 // present, or use the default trim_length size.
                 $display_options = entity_get_display('node', $node->getType(), 'teaser')->getComponent('body');
-                if (isset($display_options['settings']['trim_length'])) {
+                if ($display_options && $display_options['type'] === 'text_summary_or_trimmed') {
                   $length = $display_options['settings']['trim_length'];
                 }
                 else {
diff --git a/core/modules/node/tests/src/Kernel/NodeTokenReplaceTest.php b/core/modules/node/tests/src/Kernel/NodeTokenReplaceTest.php
index c496c83..d2825fb 100644
--- a/core/modules/node/tests/src/Kernel/NodeTokenReplaceTest.php
+++ b/core/modules/node/tests/src/Kernel/NodeTokenReplaceTest.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
+use Drupal\node\NodeInterface;
 use Drupal\Tests\system\Kernel\Token\TokenReplaceKernelTestBase;
 
 /**
@@ -18,6 +19,13 @@
 class NodeTokenReplaceTest extends TokenReplaceKernelTestBase {
 
   /**
+   * User account used as node author.
+   *
+   * @var \Drupal\user\Entity\User
+   */
+  protected $account;
+
+  /**
    * Modules to enable.
    *
    * @var array
@@ -34,24 +42,25 @@ protected function setUp() {
     $node_type = NodeType::create(['type' => 'article', 'name' => 'Article']);
     $node_type->save();
     node_add_body_field($node_type);
+
+    $this->account = $this->createUser();
   }
 
   /**
-   * Creates a node, then tests the tokens generated from it.
+   * Tests all node tokens.
    */
-  function testNodeTokenReplacement() {
+  public function testNodeTokenReplacement() {
     $url_options = array(
       'absolute' => TRUE,
       'language' => $this->interfaceLanguage,
     );
 
-    // Create a user and a node.
-    $account = $this->createUser();
+    // Create a node.
     /* @var $node \Drupal\node\NodeInterface */
     $node = Node::create([
       'type' => 'article',
       'tnid' => 0,
-      'uid' => $account->id(),
+      'uid' => $this->account->id(),
       'title' => '<blink>Blinking Text</blink>',
       'body' => [['value' => 'Regular NODE body for the test.', 'summary' => 'Fancy NODE summary.', 'format' => 'plain_text']],
     ]);
@@ -69,9 +78,9 @@ function testNodeTokenReplacement() {
     $tests['[node:langcode]'] = $node->language()->getId();
     $tests['[node:url]'] = $node->url('canonical', $url_options);
     $tests['[node:edit-url]'] = $node->url('edit-form', $url_options);
-    $tests['[node:author]'] = $account->getUsername();
+    $tests['[node:author]'] = $this->account->getUsername();
     $tests['[node:author:uid]'] = $node->getOwnerId();
-    $tests['[node:author:name]'] = $account->getUsername();
+    $tests['[node:author:name]'] = $this->account->getUsername();
     $tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getCreatedTime(), array('langcode' => $this->interfaceLanguage->getId()));
     $tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime(), array('langcode' => $this->interfaceLanguage->getId()));
 
@@ -102,30 +111,96 @@ function testNodeTokenReplacement() {
     foreach ($tests as $input => $expected) {
       $bubbleable_metadata = new BubbleableMetadata();
       $output = $this->tokenService->replace($input, array('node' => $node), array('langcode' => $this->interfaceLanguage->getId()), $bubbleable_metadata);
-      $this->assertEqual($output, $expected, format_string('Node token %token replaced.', ['%token' => $input]));
+      $this->assertEqual($output, $expected, new FormattableMarkup('Node token %token replaced.', ['%token' => $input]));
       $this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
     }
+  }
 
-    // Repeat for a node without a summary.
+  /**
+   * Tests the [node:summary] token.
+   */
+  public function testNodeSummaryTokenReplacement() {
+    // Create a node.
+    $text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi diam dui, finibus et purus ac, elementum pretium augue. '
+        . 'Fusce lacus nisl, feugiat sit amet blandit sed, mattis eu ligula. Duis laoreet dui non felis maximus fringilla. '
+        . 'Maecenas tempor magna id urna dapibus, in elementum mauris consequat. '
+        . 'Praesent in urna non felis fringilla ullamcorper interdum eu risus. '
+        . 'Vestibulum id erat ultrices, varius est sed, dignissim dui. Vestibulum a dapibus nisl. '
+        . 'Maecenas vestibulum nibh a aliquet mollis. Donec ac justo eget justo interdum faucibus. '
+        . 'Aenean sit amet finibus turpis. Donec viverra vel eros eget varius. Praesent rutrum est diam. '
+        . 'Mauris at odio scelerisque, mattis mi et, tempor eros. '
+        . 'Vestibulum sollicitudin sem quis diam sollicitudin posuere. Nam finibus vestibulum suscipit. '
+        . 'Fusce tempor tincidunt lorem vitae mollis.'; // 828
+    /* @var $node \Drupal\node\NodeInterface */
     $node = Node::create([
       'type' => 'article',
-      'uid' => $account->id(),
+      'uid' => $this->account->id(),
       'title' => '<blink>Blinking Text</blink>',
-      'body' => [['value' => 'A string that looks random like TR5c2I', 'format' => 'plain_text']],
+      'body' => [['value' => $text, 'format' => 'plain_text']],
     ]);
     $node->save();
 
-    // Generate and test token - use full body as expected value.
-    $tests = array();
-    $tests['[node:summary]'] = $node->body->processed;
+    // Get teaser node view display.
+    $view_display = \Drupal::entityTypeManager()
+        ->getStorage('entity_view_display')
+        ->load('node.article.teaser');
+    if (!$view_display) {
+      $values = [
+        'targetEntityType' => 'node',
+        'bundle' => 'article',
+        'mode' => 'teaser',
+        'status' => TRUE,
+      ];
+      $view_display = \Drupal::entityTypeManager()
+          ->getStorage('entity_view_display')
+          ->create($values);
+    }
 
-    // Test to make sure that we generated something for each token.
-    $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated for node without a summary.');
+    // Token [node:summary] should use trim settings of "Summary or trimmed"
+    // formatter of teaser view mode.
+    $view_display->setComponent('body', [
+      'type' => 'text_summary_or_trimmed',
+      'settings' => ['trim_length' => 130],
+    ]);
+    $view_display->save();
+    $expected_trimmed_to_130 = Html::escape('<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi diam dui, finibus et purus ac, elementum pretium augue.');
+    $this->assertNodeSummaryTokenReplacement($node, $expected_trimmed_to_130);
+
+    // Token [node:summary] should not pickup trim length setting of any other
+    // formatter rather than "Summary or trimmed", even if setting name matches.
+    // Fallbacks to "Summary or trimmed" default trim length setting (600).
+    $view_display->setComponent('body', [
+      'type' => 'text_trimmed',
+      'settings' => ['trim_length' => 42],
+    ]);
+    $view_display->save();
+    $expected_trimmed_to_600 = Html::escape('<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
+        . 'Morbi diam dui, finibus et purus ac, elementum pretium augue. Fusce lacus nisl, feugiat sit amet blandit sed, mattis eu ligula. '
+        . 'Duis laoreet dui non felis maximus fringilla. Maecenas tempor magna id urna dapibus, in elementum mauris consequat. '
+        . 'Praesent in urna non felis fringilla ullamcorper interdum eu risus. '
+        . 'Vestibulum id erat ultrices, varius est sed, dignissim dui. Vestibulum a dapibus nisl. '
+        . 'Maecenas vestibulum nibh a aliquet mollis. Donec ac justo eget justo interdum faucibus. '
+        . 'Aenean sit amet finibus turpis.');
+    $this->assertNodeSummaryTokenReplacement($node, $expected_trimmed_to_600);
+
+    // Token [node:summary] should not pickup trim length setting if teaser
+    // view mode does not exist.
+    // Fallbacks to "Summary or trimmed" default trim length setting (600).
+    $view_display->delete();
+    $this->assertNodeSummaryTokenReplacement($node, $expected_trimmed_to_600);
+  }
 
-    foreach ($tests as $input => $expected) {
-      $output = $this->tokenService->replace($input, array('node' => $node), array('language' => $this->interfaceLanguage));
-      $this->assertEqual($output, $expected, new FormattableMarkup('Node token %token replaced for node without a summary.', ['%token' => $input]));
-    }
+  /**
+   * Asserts that [node:summary] token works as expected.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   Node to assert against.
+   * @param string $expected
+   *   Expected token replacement output.
+   */
+  protected function assertNodeSummaryTokenReplacement(NodeInterface $node, $expected) {
+    $output = $this->tokenService->replace('[node:summary]', array('node' => $node), array('langcode' => $this->interfaceLanguage->getId()));
+    $this->assertEqual($output, $expected, new FormattableMarkup('Node token %token replaced.', ['%token' => '[node:summary]']));
   }
 
 }
