diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/NodeContextualLinksTest.php b/core/modules/node/lib/Drupal/node/Tests/Views/NodeContextualLinksTest.php
new file mode 100644
index 0000000..cf24cba
--- /dev/null
+++ b/core/modules/node/lib/Drupal/node/Tests/Views/NodeContextualLinksTest.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\node\Tests\Views\NodeContextualLinksTest.
+ */
+
+namespace Drupal\node\Tests\Views;
+
+use Drupal\Component\Utility\Json;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Tests views contextual links on nodes.
+ */
+class NodeContextualLinksTest extends NodeTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('contextual');
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = array('test_contextual_links');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Node: contextual links',
+      'description' => 'Tests views contextual links on nodes.',
+      'group' => 'Views module integration',
+    );
+  }
+
+  /**
+   * Tests contextual links.
+   */
+  public function testNodeContextualLinks() {
+    $this->drupalCreateNode(array('promote' => 1));
+    $this->drupalGet('node');
+
+    $user = $this->drupalCreateUser(array('administer nodes', 'access contextual links'));
+    $this->drupalLogin($user);
+
+    $response = $this->renderContextualLinks(array('node:node:1:'), 'node');
+    $this->assertResponse(200);
+    $json = Json::decode($response);
+    $this->drupalSetContent($json['node:node:1:']);
+
+    $this->assertLinkByHref('node/1/contextual-links', 0, 'The contextual link to the view was found.');
+    $this->assertLink('Test contextual link', 0, 'The contextual link to the view was found.');
+  }
+
+  /**
+   * Get server-rendered contextual links for the given contextual link ids.
+   *
+   * Copied from \Drupal\contextual\Tests\ContextualDynamicContextTest::renderContextualLinks().
+   *
+   * @param array $ids
+   *   An array of contextual link ids.
+   * @param string $current_path
+   *   The Drupal path for the page for which the contextual links are rendered.
+   *
+   * @return string
+   *   The response body.
+   */
+  protected function renderContextualLinks($ids, $current_path) {
+    // Build POST values.
+    $post = array();
+    for ($i = 0; $i < count($ids); $i++) {
+      $post['ids[' . $i . ']'] = $ids[$i];
+    }
+
+    // Serialize POST values.
+    foreach ($post as $key => $value) {
+      // Encode according to application/x-www-form-urlencoded
+      // Both names and values needs to be urlencoded, according to
+      // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
+      $post[$key] = urlencode($key) . '=' . urlencode($value);
+    }
+    $post = implode('&', $post);
+
+    // Perform HTTP request.
+    return $this->curlExec(array(
+      CURLOPT_URL => url('contextual/render', array('absolute' => TRUE, 'query' => array('destination' => $current_path))),
+      CURLOPT_POST => TRUE,
+      CURLOPT_POSTFIELDS => $post,
+      CURLOPT_HTTPHEADER => array(
+        'Accept: application/json',
+        'Content-Type: application/x-www-form-urlencoded',
+      ),
+    ));
+  }
+
+}
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml
new file mode 100644
index 0000000..7d807a8
--- /dev/null
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_contextual_links.yml
@@ -0,0 +1,98 @@
+base_field: nid
+base_table: node
+core: 8.x
+description: ''
+status: '1'
+display:
+  default:
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: none
+        options: {  }
+      pager:
+        type: full
+        options:
+          items_per_page: '10'
+          offset: '0'
+          id: '0'
+          total_pages: ''
+          expose:
+            items_per_page: '0'
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 20, 40, 60'
+            items_per_page_options_all: '0'
+            items_per_page_options_all_label: '- All -'
+            offset: '0'
+            offset_label: Offset
+          tags:
+            previous: '‹ previous'
+            next: 'next ›'
+            first: '« first'
+            last: 'last »'
+          quantity: '9'
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: '0'
+          distinct: '0'
+          slave: '0'
+          query_comment: ''
+          query_tags: {  }
+      row:
+        type: 'entity:node'
+        options:
+          build_mode: teaser
+          comments: '0'
+          links: '1'
+          view_mode: teaser
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: '1'
+          row_class_special: '1'
+          uses_fields: '0'
+      title: ''
+      header: {  }
+      footer: {  }
+      relationships: {  }
+      fields: {  }
+      arguments: {  }
+    display_plugin: default
+    display_title: Master
+    id: default
+    position: '0'
+  page_1:
+    display_options:
+      path: node/%/contextual-links
+      defaults:
+        arguments: '0'
+      arguments:
+        nid:
+          field: nid
+          id: nid
+          relationship: none
+          table: node
+          plugin_id: numeric
+          provider: views
+      menu:
+        type: tab
+        title: 'Test contextual link'
+        description: ''
+        name: tools
+        weight: '0'
+        context: '1'
+    display_plugin: page
+    display_title: Page
+    id: page_1
+    position: '1'
+label: Contextual links
+module: node
+id: test_contextual_links
+tag: default
+langcode: en
