From 6e3c5624ba8a21b9351ca55a91781ec2b3c761ed Mon Sep 17 00:00:00 2001
From: florenttorregrosa <florenttorregrosa@2388214.no-reply.drupal.org>
Date: Mon, 10 Apr 2017 14:37:54 +0200
Subject: [PATCH] Issue #2864680 by Grimreaper, e0ipso: Impossible to have an
 entity referencing multiple times another entity

---
 schema.json                                        |  3 +-
 .../JsonApiFunctionalMultilingualTest.php          |  2 +-
 tests/src/Functional/JsonApiFunctionalTest.php     | 18 ++++++++++--
 tests/src/Functional/JsonApiFunctionalTestBase.php | 34 +++++++++++++++-------
 4 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/schema.json b/schema.json
index 902a39d..7a2b7c8 100644
--- a/schema.json
+++ b/schema.json
@@ -251,8 +251,7 @@
       "type": "array",
       "items": {
         "$ref": "#/definitions/linkage"
-      },
-      "uniqueItems": true
+      }
     },
     "empty": {
       "description": "Describes an empty to-one relationship.",
diff --git a/tests/src/Functional/JsonApiFunctionalMultilingualTest.php b/tests/src/Functional/JsonApiFunctionalMultilingualTest.php
index 998f414..d072337 100644
--- a/tests/src/Functional/JsonApiFunctionalMultilingualTest.php
+++ b/tests/src/Functional/JsonApiFunctionalMultilingualTest.php
@@ -42,7 +42,7 @@ class JsonApiFunctionalMultilingualTest extends JsonApiFunctionalTestBase {
    * Tests reading multilingual content.
    */
   public function testReadMultilingual() {
-    $this->createDefaultContent(5, 5, TRUE, TRUE, static::IS_MULTILINGUAL);
+    $this->createDefaultContent(5, 5, TRUE, TRUE, static::IS_MULTILINGUAL, FALSE);
 
     // Test reading an individual entity.
     $output = Json::decode($this->drupalGet('/ca/jsonapi/node/article/' . $this->nodes[0]->uuid(), ['query' => ['include' => 'field_tags,field_image']]));
diff --git a/tests/src/Functional/JsonApiFunctionalTest.php b/tests/src/Functional/JsonApiFunctionalTest.php
index 366ab7e..f7a1030 100644
--- a/tests/src/Functional/JsonApiFunctionalTest.php
+++ b/tests/src/Functional/JsonApiFunctionalTest.php
@@ -15,7 +15,7 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase {
    * Test the GET method.
    */
   public function testRead() {
-    $this->createDefaultContent(61, 5, TRUE, TRUE, static::IS_NOT_MULTILINGUAL);
+    $this->createDefaultContent(61, 5, TRUE, TRUE, static::IS_NOT_MULTILINGUAL, FALSE);
     // Unpublish the last entity, so we can check access.
     $this->nodes[60]->setUnpublished()->save();
 
@@ -262,10 +262,24 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase {
   }
 
   /**
+   * Test the GET method on articles referencing the same tag twice.
+   */
+  public function testReferencingTwiceRead() {
+    $this->createDefaultContent(1, 1, FALSE, FALSE, static::IS_NOT_MULTILINGUAL, TRUE);
+
+    // 1. Load all articles (1st page).
+    $collection_output = Json::decode($this->drupalGet('/jsonapi/node/article'));
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertEquals(1, count($collection_output['data']));
+    $this->assertSession()
+      ->responseHeaderEquals('Content-Type', 'application/vnd.api+json');
+  }
+
+  /**
    * Test POST, PATCH and DELETE.
    */
   public function testWrite() {
-    $this->createDefaultContent(0, 3, FALSE, FALSE, static::IS_NOT_MULTILINGUAL);
+    $this->createDefaultContent(0, 3, FALSE, FALSE, static::IS_NOT_MULTILINGUAL, FALSE);
     // 1. Successful post.
     $collection_url = Url::fromRoute('jsonapi.node--article.collection');
     $body = [
diff --git a/tests/src/Functional/JsonApiFunctionalTestBase.php b/tests/src/Functional/JsonApiFunctionalTestBase.php
index 1a648f3..f4107c2 100644
--- a/tests/src/Functional/JsonApiFunctionalTestBase.php
+++ b/tests/src/Functional/JsonApiFunctionalTestBase.php
@@ -193,8 +193,11 @@ abstract class JsonApiFunctionalTestBase extends BrowserTestBase {
    *   Set to TRUE if you want to add a link to the generated articles.
    * @param bool $is_multilingual
    *   (optional) Set to TRUE if you want to enable multilingual content.
+   * @param bool $referencing_twice
+   *   (optional) Set to TRUE if you want articles to reference the same tag
+   *   twice.
    */
-  protected function createDefaultContent($num_articles, $num_tags, $article_has_image, $article_has_link, $is_multilingual) {
+  protected function createDefaultContent($num_articles, $num_tags, $article_has_image, $article_has_link, $is_multilingual, $referencing_twice = FALSE) {
     $random = $this->getRandomGenerator();
     for ($created_tags = 0; $created_tags < $num_tags; $created_tags++) {
       $term = Term::create([
@@ -210,20 +213,29 @@ abstract class JsonApiFunctionalTestBase extends BrowserTestBase {
       $this->tags[] = $term;
     }
     for ($created_nodes = 0; $created_nodes < $num_articles; $created_nodes++) {
-      // Get N random tags.
-      $selected_tags = mt_rand(1, $num_tags);
-      $tags = [];
-      while (count($tags) < $selected_tags) {
-        $tags[] = mt_rand(1, $num_tags);
-        $tags = array_unique($tags);
-      }
       $values = [
         'uid' => ['target_id' => $this->user->id()],
         'type' => 'article',
-        'field_tags' => array_map(function ($tag) {
-          return ['target_id' => $tag];
-        }, $tags),
       ];
+
+      if ($referencing_twice) {
+        $values['field_tags'] = [
+          ['target_id' => 1],
+          ['target_id' => 1],
+        ];
+      }
+      else {
+        // Get N random tags.
+        $selected_tags = mt_rand(1, $num_tags);
+        $tags = [];
+        while (count($tags) < $selected_tags) {
+          $tags[] = mt_rand(1, $num_tags);
+          $tags = array_unique($tags);
+        }
+        $values['field_tags'] = array_map(function ($tag) {
+          return ['target_id' => $tag];
+        }, $tags);
+      }
       if ($article_has_image) {
         $file = File::create([
           'uri' => 'vfs://' . $random->name() . '.png',
-- 
1.9.1

