From 9a02500d9b97994e9d75c084d470987eb33edb03 Mon Sep 17 00:00:00 2001
From: Brian Canini <canini.16@osu.edu>
Date: Thu, 25 Jun 2020 14:28:38 -0400
Subject: [PATCH] Updating drupal/inline_entity_form (1.0.0-rc1 => 1.0.0-rc6)

---
 composer.json                                 |   2 +-
 composer.lock                                 |  47 +-
 vendor/composer/installed.json                |  47 +-
 .../.travis-before-script.sh                  |   0
 web/modules/inline_entity_form/README         |   4 +-
 web/modules/inline_entity_form/composer.json  |   9 +-
 .../schema/inline_entity_form.schema.yml      |  14 +-
 .../css/commerce-product.css                  |  11 -
 .../css/inline_entity_form.css                |  38 -
 .../css/inline_entity_form.seven.css          |  31 -
 .../inline_entity_form.info.yml               |  11 +-
 .../inline_entity_form.libraries.yml          |  15 -
 .../js/inline_entity_form.js                  |  29 -
 .../src/Element/InlineEntityForm.php          |  17 +-
 .../inline_entity_form/src/ElementSubmit.php  |   4 +-
 .../src/Form/EntityInlineForm.php             |  21 +-
 .../src/Form/NodeInlineForm.php               |  12 -
 .../src/InlineFormInterface.php               |  18 +-
 .../FieldWidget/InlineEntityFormBase.php      |  15 +-
 .../FieldWidget/InlineEntityFormComplex.php   | 104 +-
 .../FieldWidget/InlineEntityFormSimple.php    |  14 +-
 .../src/Tests/ComplexSimpleWidgetTest.php     | 111 ---
 .../src/Tests/ComplexWidgetWebTest.php        | 780 ---------------
 .../src/Tests/ElementWebTest.php              |  82 --
 .../src/Tests/InlineEntityFormTestBase.php    | 188 ----
 .../src/Tests/SimpleWidgetWebTest.php         | 248 -----
 .../src/Tests/TranslationTest.php             | 173 ----
 ...isplay.node.ief_complex_simple.default.yml |   1 +
 ...isplay.node.ief_reference_type.default.yml |   1 +
 ...de.ief_simple_entity_no_bundle.default.yml |   2 +-
 ...display.node.ief_simple_single.default.yml |   1 +
 ..._display.node.ief_test_complex.default.yml |   1 +
 ...m_display.node.ief_test_custom.default.yml |   1 +
 ..._display.node.ief_test_nested1.default.yml |   1 +
 ..._display.node.ief_test_nested2.default.yml |   1 +
 ..._display.node.ief_test_nested3.default.yml |   1 +
 ...y_no_bundle.field_ief_entity_no_bundle.yml |   1 -
 ...torage.node.field_ief_entity_no_bundle.yml |   1 -
 .../node.type.ief_simple_entity_no_bundle.yml |   1 -
 ...ield_override.node.err_level_1.promote.yml |  21 +
 ...ield_override.node.err_level_2.promote.yml |  21 +
 ...ield_override.node.err_level_3.promote.yml |  21 +
 ..._form_display.node.err_level_1.default.yml |  62 ++
 ..._form_display.node.err_level_2.default.yml |  38 +
 ..._form_display.node.err_level_3.default.yml |  23 +
 ..._view_display.node.err_level_1.default.yml |  34 +
 ...y_view_display.node.err_level_1.teaser.yml |  16 +
 ..._view_display.node.err_level_2.default.yml |  25 +
 ...y_view_display.node.err_level_2.teaser.yml |  16 +
 ..._view_display.node.err_level_3.default.yml |  15 +
 ...y_view_display.node.err_level_3.teaser.yml |  16 +
 ...level_1.field_level_2_entity_no_bundle.yml |  27 +
 ...d.node.err_level_1.field_level_2_items.yml |  29 +
 ...d.node.err_level_2.field_level_3_items.yml |  29 +
 ...ge.node.field_level_2_entity_no_bundle.yml |  21 +
 ...field.storage.node.field_level_2_items.yml |  19 +
 ...field.storage.node.field_level_3_items.yml |  19 +
 .../config/optional/node.type.err_level_1.yml |   9 +
 .../config/optional/node.type.err_level_2.yml |   9 +
 .../config/optional/node.type.err_level_3.yml |   9 +
 .../inline_entity_form_test.info.yml          |  18 +-
 .../inline_entity_form_test/src/IefTest.php   |   3 +-
 ...ntent_settings.node.ief_reference_type.yml |  17 +
 ...content_settings.node.ief_test_complex.yml |  17 +
 ...line_entity_form_translation_test.info.yml |  14 +
 .../ComplexSimpleWidgetTest.php               | 124 +++
 .../ComplexWidgetRevisionsTest.php            | 263 +++++
 .../ComplexWidgetTest.php                     | 909 ++++++++++++++++++
 .../FunctionalJavascript/ElementWebTest.php   |  88 ++
 .../InlineEntityFormTestBase.php              | 319 ++++++
 .../FunctionalJavascript/SimpleWidgetTest.php | 323 +++++++
 .../FunctionalJavascript/TranslationTest.php  | 167 ++++
 72 files changed, 2981 insertions(+), 1818 deletions(-)
 mode change 100644 => 100755 web/modules/inline_entity_form/.travis-before-script.sh
 delete mode 100644 web/modules/inline_entity_form/css/commerce-product.css
 delete mode 100644 web/modules/inline_entity_form/css/inline_entity_form.css
 delete mode 100644 web/modules/inline_entity_form/css/inline_entity_form.seven.css
 delete mode 100644 web/modules/inline_entity_form/inline_entity_form.libraries.yml
 delete mode 100644 web/modules/inline_entity_form/js/inline_entity_form.js
 delete mode 100644 web/modules/inline_entity_form/src/Tests/ComplexSimpleWidgetTest.php
 delete mode 100644 web/modules/inline_entity_form/src/Tests/ComplexWidgetWebTest.php
 delete mode 100644 web/modules/inline_entity_form/src/Tests/ElementWebTest.php
 delete mode 100644 web/modules/inline_entity_form/src/Tests/InlineEntityFormTestBase.php
 delete mode 100644 web/modules/inline_entity_form/src/Tests/SimpleWidgetWebTest.php
 delete mode 100644 web/modules/inline_entity_form/src/Tests/TranslationTest.php
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_reference_type.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_test_complex.yml
 create mode 100644 web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/inline_entity_form_translation_test.info.yml
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexSimpleWidgetTest.php
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetTest.php
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/ElementWebTest.php
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/InlineEntityFormTestBase.php
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/SimpleWidgetTest.php
 create mode 100644 web/modules/inline_entity_form/tests/src/FunctionalJavascript/TranslationTest.php

diff --git a/composer.json b/composer.json
index 9a1fb922e5..bdc268f574 100644
--- a/composer.json
+++ b/composer.json
@@ -129,7 +129,7 @@
         "drupal/google_tag": "1.4",
         "drupal/honeypot": "1.30",
         "drupal/image_popup": "1.1",
-        "drupal/inline_entity_form": "1.0-rc1",
+        "drupal/inline_entity_form": "1.0-rc6",
         "drupal/libraries": "3.0.0-alpha1",
         "drupal/link_attributes": "1.10",
         "drupal/linkit": "5.0-beta11",
diff --git a/composer.lock b/composer.lock
index 2e1c59c874..c2e27f1d56 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "b92b53385fd085532a6ff33f1dc006cb",
+    "content-hash": "6a15808ea43555a7d6d68dd3386988f6",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -5321,32 +5321,29 @@
         },
         {
             "name": "drupal/inline_entity_form",
-            "version": "1.0.0-rc1",
+            "version": "1.0.0-rc6",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/inline_entity_form.git",
-                "reference": "8.x-1.0-rc1"
+                "reference": "8.x-1.0-rc6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/inline_entity_form-8.x-1.0-rc1.zip",
-                "reference": "8.x-1.0-rc1",
-                "shasum": "898789fb6a0662fc2572b87f8d0654a0241473f9"
+                "url": "https://ftp.drupal.org/files/projects/inline_entity_form-8.x-1.0-rc6.zip",
+                "reference": "8.x-1.0-rc6",
+                "shasum": "9f7508f4cb88d5e7869c81b20b44d89bc1689fad"
             },
             "require": {
-                "drupal/core": "~8.0"
+                "drupal/core": "^8.7.7 || ^9"
             },
             "require-dev": {
-                "drupal/entity_reference_revisions": "*"
+                "drupal/entity_reference_revisions": "^1.0"
             },
             "type": "drupal-module",
             "extra": {
-                "branch-alias": {
-                    "dev-1.x": "1.x-dev"
-                },
                 "drupal": {
-                    "version": "8.x-1.0-rc1",
-                    "datestamp": "1527030784",
+                    "version": "8.x-1.0-rc6",
+                    "datestamp": "1589280847",
                     "security-coverage": {
                         "status": "not-covered",
                         "message": "RC releases are not covered by Drupal security advisories."
@@ -5355,7 +5352,7 @@
             },
             "notification-url": "https://packages.drupal.org/8/downloads",
             "license": [
-                "GPL-2.0+"
+                "GPL-2.0-or-later"
             ],
             "authors": [
                 {
@@ -5366,6 +5363,26 @@
                     "name": "dawehner",
                     "homepage": "https://www.drupal.org/user/99340"
                 },
+                {
+                    "name": "geek-merlin",
+                    "homepage": "https://www.drupal.org/user/229048"
+                },
+                {
+                    "name": "joachim",
+                    "homepage": "https://www.drupal.org/user/107701"
+                },
+                {
+                    "name": "jsacksick",
+                    "homepage": "https://www.drupal.org/user/972218"
+                },
+                {
+                    "name": "kaythay",
+                    "homepage": "https://www.drupal.org/user/2182186"
+                },
+                {
+                    "name": "oknate",
+                    "homepage": "https://www.drupal.org/user/471638"
+                },
                 {
                     "name": "rszrama",
                     "homepage": "https://www.drupal.org/user/49344"
@@ -5382,7 +5399,7 @@
             "description": "Provides a widget for inline management (creation, modification, removal) of referenced entities.",
             "homepage": "https://www.drupal.org/project/inline_entity_form",
             "support": {
-                "source": "http://cgit.drupalcode.org/inline_entity_form"
+                "source": "https://git.drupalcode.org/project/inline_entity_form"
             }
         },
         {
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index b65f2ce7a2..fdf14cf5db 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -5481,33 +5481,30 @@
     },
     {
         "name": "drupal/inline_entity_form",
-        "version": "1.0.0-rc1",
-        "version_normalized": "1.0.0.0-RC1",
+        "version": "1.0.0-rc6",
+        "version_normalized": "1.0.0.0-RC6",
         "source": {
             "type": "git",
             "url": "https://git.drupalcode.org/project/inline_entity_form.git",
-            "reference": "8.x-1.0-rc1"
+            "reference": "8.x-1.0-rc6"
         },
         "dist": {
             "type": "zip",
-            "url": "https://ftp.drupal.org/files/projects/inline_entity_form-8.x-1.0-rc1.zip",
-            "reference": "8.x-1.0-rc1",
-            "shasum": "898789fb6a0662fc2572b87f8d0654a0241473f9"
+            "url": "https://ftp.drupal.org/files/projects/inline_entity_form-8.x-1.0-rc6.zip",
+            "reference": "8.x-1.0-rc6",
+            "shasum": "9f7508f4cb88d5e7869c81b20b44d89bc1689fad"
         },
         "require": {
-            "drupal/core": "~8.0"
+            "drupal/core": "^8.7.7 || ^9"
         },
         "require-dev": {
-            "drupal/entity_reference_revisions": "*"
+            "drupal/entity_reference_revisions": "^1.0"
         },
         "type": "drupal-module",
         "extra": {
-            "branch-alias": {
-                "dev-1.x": "1.x-dev"
-            },
             "drupal": {
-                "version": "8.x-1.0-rc1",
-                "datestamp": "1527030784",
+                "version": "8.x-1.0-rc6",
+                "datestamp": "1589280847",
                 "security-coverage": {
                     "status": "not-covered",
                     "message": "RC releases are not covered by Drupal security advisories."
@@ -5517,7 +5514,7 @@
         "installation-source": "dist",
         "notification-url": "https://packages.drupal.org/8/downloads",
         "license": [
-            "GPL-2.0+"
+            "GPL-2.0-or-later"
         ],
         "authors": [
             {
@@ -5528,6 +5525,26 @@
                 "name": "dawehner",
                 "homepage": "https://www.drupal.org/user/99340"
             },
+            {
+                "name": "geek-merlin",
+                "homepage": "https://www.drupal.org/user/229048"
+            },
+            {
+                "name": "joachim",
+                "homepage": "https://www.drupal.org/user/107701"
+            },
+            {
+                "name": "jsacksick",
+                "homepage": "https://www.drupal.org/user/972218"
+            },
+            {
+                "name": "kaythay",
+                "homepage": "https://www.drupal.org/user/2182186"
+            },
+            {
+                "name": "oknate",
+                "homepage": "https://www.drupal.org/user/471638"
+            },
             {
                 "name": "rszrama",
                 "homepage": "https://www.drupal.org/user/49344"
@@ -5544,7 +5561,7 @@
         "description": "Provides a widget for inline management (creation, modification, removal) of referenced entities.",
         "homepage": "https://www.drupal.org/project/inline_entity_form",
         "support": {
-            "source": "http://cgit.drupalcode.org/inline_entity_form"
+            "source": "https://git.drupalcode.org/project/inline_entity_form"
         }
     },
     {
diff --git a/web/modules/inline_entity_form/.travis-before-script.sh b/web/modules/inline_entity_form/.travis-before-script.sh
old mode 100644
new mode 100755
diff --git a/web/modules/inline_entity_form/README b/web/modules/inline_entity_form/README
index c9e7a6e2af..b90bc86ef1 100644
--- a/web/modules/inline_entity_form/README
+++ b/web/modules/inline_entity_form/README
@@ -32,9 +32,9 @@ Integrating with Inline Entity Form
 An entity type can add support for this module by declaring the
 inline entity form controller class in its entity info:
 
-$entity_info['commerce_line_item']['inline_form'] = array(
+$entity_info['commerce_line_item']['inline_form'] = [
   'controller' => 'CommerceLineItemInlineEntityFormController',
-);
+];
 
 The controller needs to extend EntityInlineEntityFormController and at least
 override entityForm() to provide a functioning entity form.
diff --git a/web/modules/inline_entity_form/composer.json b/web/modules/inline_entity_form/composer.json
index 098227624b..3d5471ab42 100644
--- a/web/modules/inline_entity_form/composer.json
+++ b/web/modules/inline_entity_form/composer.json
@@ -2,7 +2,12 @@
   "name": "drupal/inline_entity_form",
   "description": "Provides a widget for inline management (creation, modification, removal) of referenced entities.",
   "type": "drupal-module",
-  "license": "GPL-2.0+",
+  "license": "GPL-2.0-or-later",
   "minimum-stability": "dev",
-  "require": { }
+  "require": {
+    "drupal/core": "^8.7.7 || ^9"
+  },
+  "require-dev": {
+    "drupal/entity_reference_revisions": "^1.0"
+  }
 }
diff --git a/web/modules/inline_entity_form/config/schema/inline_entity_form.schema.yml b/web/modules/inline_entity_form/config/schema/inline_entity_form.schema.yml
index aef7d466ed..b962119ea2 100644
--- a/web/modules/inline_entity_form/config/schema/inline_entity_form.schema.yml
+++ b/web/modules/inline_entity_form/config/schema/inline_entity_form.schema.yml
@@ -11,10 +11,10 @@ field.widget.settings.inline_entity_form_simple:
       type: boolean
       label: "Override labels"
     label_singular:
-      type: string
+      type: label
       label: "Label (singular)"
     label_plural:
-      type: string
+      type: label
       label: "Label (plural)"
     allow_new:
       type: boolean
@@ -31,6 +31,9 @@ field.widget.settings.inline_entity_form_simple:
     collapsed:
       type: boolean
       label: "Collapsed by default"
+    revision:
+      type: boolean
+      label: "Create new revision"
 
 field.widget.settings.inline_entity_form_complex:
   type: mapping
@@ -43,10 +46,10 @@ field.widget.settings.inline_entity_form_complex:
       type: boolean
       label: "Override labels"
     label_singular:
-      type: string
+      type: label
       label: "Label (singular)"
     label_plural:
-      type: string
+      type: label
       label: "Label (plural)"
     allow_new:
       type: boolean
@@ -66,3 +69,6 @@ field.widget.settings.inline_entity_form_complex:
     collapsed:
       type: boolean
       label: "Collapsed by default"
+    revision:
+      type: boolean
+      label: "Create new revision"
diff --git a/web/modules/inline_entity_form/css/commerce-product.css b/web/modules/inline_entity_form/css/commerce-product.css
deleted file mode 100644
index 92ef167a03..0000000000
--- a/web/modules/inline_entity_form/css/commerce-product.css
+++ /dev/null
@@ -1,11 +0,0 @@
-
-.ief-product-attributes .fieldset-wrapper {
-  margin-top: 15px;
-}
-.ief-product-attributes .fieldset-wrapper > div {
-  margin-right: 20px;
-}
-
-.ief-product-details .field-type-commerce-price .form-item {
-  margin-right: 15px;
-}
diff --git a/web/modules/inline_entity_form/css/inline_entity_form.css b/web/modules/inline_entity_form/css/inline_entity_form.css
deleted file mode 100644
index cfb561951b..0000000000
--- a/web/modules/inline_entity_form/css/inline_entity_form.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.ief-cardinality-count {
-  text-align: right;
-  font-size: 0.9em;
-}
-
-.ief-tabledrag-header {
-  border-right: none;
-}
-
-.ief-sort-order-header {
-  border-left: none;
-}
-
-.ief-first-column-header {
-  border-left: none;
-}
-
-.ief-tabledrag-handle {
-  padding-right: 0;
-  width: 20px;
-}
-
-.ief-tabledrag-handle a.tabledrag-handle {
-  padding-right: .5em;
-}
-
-fieldset.ief-entity-fieldset {
-  margin: 0;
-}
-
-.ief-row-form > td {
-  padding: 0;
-}
-
-.ief-row-form .ief-form-row {
-  border-bottom: 10px solid #ccc;
-  padding: 20px;
-}
diff --git a/web/modules/inline_entity_form/css/inline_entity_form.seven.css b/web/modules/inline_entity_form/css/inline_entity_form.seven.css
deleted file mode 100644
index a2d3c53ff2..0000000000
--- a/web/modules/inline_entity_form/css/inline_entity_form.seven.css
+++ /dev/null
@@ -1,31 +0,0 @@
-
-.ief-row-entity-form {
-  background-color: #D5E9F2 !important;
-}
-
-.field-widget-inline-entity-form fieldset.form-wrapper {
-  border: 0;
-}
-.ief-entity-fieldset, .ief-entity-fieldset fieldset {
-  background-color: transparent;
-}
-.ief-form > .fieldset-wrapper {
-  background: #f2f2f2;
-  border: 1px solid #ccc !important;
-}
-
-.ief-form > .fieldset-wrapper {
-  border: 1px solid #ccc !important;
-}
-
-.ief-entity-fieldset > legend span.fieldset-legend {
-  border-bottom: 1px solid #E4E4E4;
-  font-weight: 600;
-  margin-top: 10px;
-  padding: 3px 0;
-  width: 100%;
-}
-
-.ief-entity-fieldset > .fieldset-wrapper {
-  margin-top: 5px;
-}
diff --git a/web/modules/inline_entity_form/inline_entity_form.info.yml b/web/modules/inline_entity_form/inline_entity_form.info.yml
index d4b6a49d2c..5958676d6f 100644
--- a/web/modules/inline_entity_form/inline_entity_form.info.yml
+++ b/web/modules/inline_entity_form/inline_entity_form.info.yml
@@ -2,12 +2,9 @@ name: Inline Entity Form
 description: "Provides a widget for inline management (creation, modification, removal) of referenced entities. "
 type: module
 package: Fields
-# core: 8.x
-test_dependencies:
-  - entity_reference_revisions:entity_reference_revisions
+core_version_requirement: ^8.7.7 || ^9
 
-# Information added by Drupal.org packaging script on 2018-05-22
-version: '8.x-1.0-rc1'
-core: '8.x'
+# Information added by Drupal.org packaging script on 2020-05-12
+version: '8.x-1.0-rc6'
 project: 'inline_entity_form'
-datestamp: 1527030788
+datestamp: 1589280849
diff --git a/web/modules/inline_entity_form/inline_entity_form.libraries.yml b/web/modules/inline_entity_form/inline_entity_form.libraries.yml
deleted file mode 100644
index 30e27f614a..0000000000
--- a/web/modules/inline_entity_form/inline_entity_form.libraries.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-widget:
-  version: VERSION
-  js:
-    js/inline_entity_form.js: {}
-  dependencies:
-    - core/jquery
-    - core/jquery.once
-    - core/drupal
-    - core/drupalSettings
-
-commerce_product.base:
-  version: VERSION
-  css:
-    theme:
-      css/commerce-product.css: {}
diff --git a/web/modules/inline_entity_form/js/inline_entity_form.js b/web/modules/inline_entity_form/js/inline_entity_form.js
deleted file mode 100644
index f6965eb8fd..0000000000
--- a/web/modules/inline_entity_form/js/inline_entity_form.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * @file
- * Provides JavaScript for Inline Entity Form.
- */
-
-(function ($) {
-
-/**
- * Allows submit buttons in entity forms to trigger uploads by undoing
- * work done by Drupal.behaviors.fileButtons.
- */
-Drupal.behaviors.inlineEntityForm = {
-  attach: function (context) {
-    /*
-    if (Drupal.file) {
-      $('input.ief-entity-submit', context).unbind('mousedown', Drupal.file.disableFields);
-    }
-    */
-  },
-  detach: function (context) {
-    /*
-    if (Drupal.file) {
-      $('input.form-submit', context).bind('mousedown', Drupal.file.disableFields);
-    }
-    */
-  }
-};
-
-})(jQuery);
diff --git a/web/modules/inline_entity_form/src/Element/InlineEntityForm.php b/web/modules/inline_entity_form/src/Element/InlineEntityForm.php
index 0fbe2335ab..7de4012344 100644
--- a/web/modules/inline_entity_form/src/Element/InlineEntityForm.php
+++ b/web/modules/inline_entity_form/src/Element/InlineEntityForm.php
@@ -3,8 +3,8 @@
 namespace Drupal\inline_entity_form\Element;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\RevisionLogInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\RenderElement;
 use Drupal\inline_entity_form\ElementSubmit;
 use Drupal\inline_entity_form\TranslationHelper;
@@ -45,6 +45,8 @@ public function getInfo() {
       '#default_value' => NULL,
       // The form mode used to display the entity form.
       '#form_mode' => 'default',
+      // Will create a new revision if set to TRUE.
+      '#revision' => FALSE,
       // Will save entity on submit if set to TRUE.
       '#save_entity' => TRUE,
       // 'add', 'edit' or 'duplicate'.
@@ -97,6 +99,7 @@ public static function processEntityForm($entity_form, FormStateInterface $form_
       throw new \InvalidArgumentException('The inline_entity_form #default_value property must be an entity object.');
     }
 
+    $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_form['#entity_type']);
     if (empty($entity_form['#ief_id'])) {
       $entity_form['#ief_id'] = \Drupal::service('uuid')->generate();
     }
@@ -106,7 +109,6 @@ public static function processEntityForm($entity_form, FormStateInterface $form_
     }
     else {
       // This is an add operation, create a new entity.
-      $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_form['#entity_type']);
       $storage = \Drupal::entityTypeManager()->getStorage($entity_form['#entity_type']);
       $values = [];
       if ($langcode_key = $entity_type->getKey('langcode')) {
@@ -132,6 +134,17 @@ public static function processEntityForm($entity_form, FormStateInterface $form_
     $entity_form['#entity'] = TranslationHelper::prepareEntity($entity_form['#entity'], $form_state);
     $entity_form['#translating'] = TranslationHelper::isTranslating($form_state) && $entity_form['#entity']->isTranslatable();
 
+    // Handle revisioning if the entity supports it.
+    if ($entity_type->isRevisionable() && $entity_form['#revision']) {
+      $entity_form['#entity']->setNewRevision($entity_form['#revision']);
+
+      // @see \Drupal\Core\Entity\ContentEntityForm::buildEntity
+      if ($entity_form['#entity'] instanceof RevisionLogInterface) {
+        $entity_form['#entity']->setRevisionUserId(\Drupal::currentUser()->id());
+        $entity_form['#entity']->setRevisionCreationTime(\Drupal::time()->getRequestTime());
+      }
+    }
+
     $inline_form_handler = static::getInlineFormHandler($entity_form['#entity_type']);
     $entity_form = $inline_form_handler->entityForm($entity_form, $form_state);
     // The form element can't rely on inline_entity_form_form_alter() calling
diff --git a/web/modules/inline_entity_form/src/ElementSubmit.php b/web/modules/inline_entity_form/src/ElementSubmit.php
index 0abde9bb08..72e08a1228 100644
--- a/web/modules/inline_entity_form/src/ElementSubmit.php
+++ b/web/modules/inline_entity_form/src/ElementSubmit.php
@@ -72,7 +72,7 @@ public static function addCallback(&$element, $complete_form) {
    * @param \Drupal\Core\Form\FormStateInterface $form_state
    *   The form state.
    */
-  public static function trigger($form, FormStateInterface $form_state) {
+  public static function trigger(&$form, FormStateInterface $form_state) {
     $triggered_element = $form_state->getTriggeringElement();
     if (!empty($triggered_element['#ief_submit_trigger_all'])) {
       // The parent form was submitted, process all IEFs and their children.
@@ -95,7 +95,7 @@ public static function trigger($form, FormStateInterface $form_state) {
    * @param \Drupal\Core\Form\FormStateInterface $form_state
    *   The form state.
    */
-  public static function doSubmit($element, FormStateInterface $form_state) {
+  public static function doSubmit(&$element, FormStateInterface $form_state) {
     // Recurse through all children.
     foreach (Element::children($element) as $key) {
       if (!empty($element[$key])) {
diff --git a/web/modules/inline_entity_form/src/Form/EntityInlineForm.php b/web/modules/inline_entity_form/src/Form/EntityInlineForm.php
index 1ff5073792..22533e62f2 100644
--- a/web/modules/inline_entity_form/src/Form/EntityInlineForm.php
+++ b/web/modules/inline_entity_form/src/Form/EntityInlineForm.php
@@ -3,6 +3,7 @@
 namespace Drupal\inline_entity_form\Form;
 
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\ContentEntityTypeInterface;
 use Drupal\Core\Entity\Entity\EntityFormDisplay;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
@@ -11,6 +12,8 @@
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Render\Element;
 use Drupal\inline_entity_form\InlineFormInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -20,6 +23,8 @@
  */
 class EntityInlineForm implements InlineFormInterface {
 
+  use StringTranslationTrait;
+
   /**
    * The entity field manager.
    *
@@ -90,10 +95,10 @@ public function getEntityType() {
    * {@inheritdoc}
    */
   public function getEntityTypeLabels() {
-    $lowercase_label = $this->entityType->getLowercaseLabel();
+    $lowercase_label = $this->entityType->getSingularLabel();
     return [
       'singular' => $lowercase_label,
-      'plural' => t('@entity_type entities', ['@entity_type' => $lowercase_label]),
+      'plural' => $this->t('@entity_type entities', ['@entity_type' => $lowercase_label]),
     ];
   }
 
@@ -110,12 +115,12 @@ public function getEntityLabel(EntityInterface $entity) {
   public function getTableFields($bundles) {
     $definitions = $this->entityFieldManager->getBaseFieldDefinitions($this->entityType->id());
     $label_key = $this->entityType->getKey('label');
-    $label_field_label = t('Label');
+    $label_field_label = $this->t('Label');
     if ($label_key && isset($definitions[$label_key])) {
       $label_field_label = $definitions[$label_key]->getLabel();
     }
     $bundle_key = $this->entityType->getKey('bundle');
-    $bundle_field_label = t('Type');
+    $bundle_field_label = $this->t('Type');
     if ($bundle_key && isset($definitions[$bundle_key])) {
       $bundle_field_label = $definitions[$bundle_key]->getLabel();
     }
@@ -183,6 +188,14 @@ public function entityForm(array $entity_form, FormStateInterface $form_state) {
       }
     }
 
+    // Hide the log message field for revisionable entity types. It cannot be
+    // disabled in UI and does not make sense in inline entity form context.
+    if (($this->entityType instanceof ContentEntityTypeInterface)) {
+      if ($log_message_key = $this->entityType->getRevisionMetadataKey('revision_log_message')) {
+        $entity_form[$log_message_key]['#access'] = FALSE;
+      }
+    }
+
     // Determine the children of the entity form before it has been altered.
     $children_before = Element::children($entity_form);
 
diff --git a/web/modules/inline_entity_form/src/Form/NodeInlineForm.php b/web/modules/inline_entity_form/src/Form/NodeInlineForm.php
index 4f6c377001..1c00b6acdf 100644
--- a/web/modules/inline_entity_form/src/Form/NodeInlineForm.php
+++ b/web/modules/inline_entity_form/src/Form/NodeInlineForm.php
@@ -45,16 +45,4 @@ public function getTableFields($bundles) {
     return $fields;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function entityForm(array $entity_form, FormStateInterface $form_state) {
-    $entity_form = parent::entityForm($entity_form, $form_state);
-    // Remove the "Revision log" textarea,  it can't be disabled in the
-    // form display and doesn't make sense in the inline form context.
-    $entity_form['revision_log']['#access'] = FALSE;
-
-    return $entity_form;
-  }
-
 }
diff --git a/web/modules/inline_entity_form/src/InlineFormInterface.php b/web/modules/inline_entity_form/src/InlineFormInterface.php
index fe56c160f7..f7b0b2a552 100644
--- a/web/modules/inline_entity_form/src/InlineFormInterface.php
+++ b/web/modules/inline_entity_form/src/InlineFormInterface.php
@@ -43,7 +43,7 @@ public function getEntityTypeLabels();
   public function getEntityLabel(EntityInterface $entity);
 
   /**
-   * Gets the fields used to represent an entity in the IEF table.
+   * Gets the columns used to represent an entity in the IEF table.
    *
    * Modules can alter the output of this method through
    * hook_inline_entity_form_table_fields_alter().
@@ -52,14 +52,20 @@ public function getEntityLabel(EntityInterface $entity);
    *   An array of allowed bundles for this widget.
    *
    * @return array
-   *   An array of fields keyed by field name. Each field is represented by an
-   *   associative array containing the following keys:
-   *   - type: 'label', 'field' or 'callback'.
+   *   An array of data about table columns keyed by column name. Each column is
+   *   represented by an associative array containing the following keys:
+   *   - type: One of 'label', 'field' or 'callback', which indicates how this
+   *     column should be handled:
+   *      - 'label': The entity's label.
+   *      - 'field': A field value from the entity. The name of the field is
+   *        given by the key in this array.
+   *      - 'callback': A callback, given by the 'callback' property.
+   *     See theme_inline_entity_form_entity_table() for the handling of these.
    *   - label: the title of the table field's column in the IEF table.
    *   - weight: the sort order of the column in the IEF table.
-   *   - display_options: (optional) used for 'field' type table fields, an
+   *   - display_options: (optional) used for 'field' type table columns, an
    *     array of display settings. See EntityViewBuilderInterface::viewField().
-   *   - callback: for 'callback' type table fields, a callable that returns a
+   *   - callback: for 'callback' type table columns, a callable that returns a
    *     renderable array.
    *   - callback_arguments: (optional) an array of additional arguments to pass
    *     to the callback. The entity and the theme variables are always passed
diff --git a/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php b/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
index 1e69c7c9fb..471afb3426 100644
--- a/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
+++ b/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
@@ -57,7 +57,7 @@ abstract class InlineEntityFormBase extends WidgetBase implements ContainerFacto
   /**
    * Constructs an InlineEntityFormBase object.
    *
-   * @param array $plugin_id
+   * @param string $plugin_id
    *   The plugin_id for the widget.
    * @param mixed $plugin_definition
    *   The plugin implementation definition.
@@ -190,6 +190,7 @@ protected function getCreateBundles() {
   public static function defaultSettings() {
     return [
       'form_mode' => 'default',
+      'revision' => FALSE,
       'override_labels' => FALSE,
       'label_singular' => '',
       'label_plural' => '',
@@ -212,6 +213,11 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       '#options' => $this->entityDisplayRepository->getFormModeOptions($entity_type_id),
       '#required' => TRUE,
     ];
+    $element['revision'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Create new revision'),
+      '#default_value' => $this->getSetting('revision'),
+    ];
     $element['override_labels'] = [
       '#type' => 'checkbox',
       '#title' => $this->t('Override labels'),
@@ -267,7 +273,7 @@ public function settingsSummary() {
     else {
       $form_mode_label = $this->t('Default');
     }
-    $summary[] = t('Form mode: @mode', ['@mode' => $form_mode_label]);
+    $summary[] = $this->t('Form mode: @mode', ['@mode' => $form_mode_label]);
     if ($this->getSetting('override_labels')) {
       $summary[] = $this->t(
         'Overriden labels are used: %singular and %plural',
@@ -278,6 +284,10 @@ public function settingsSummary() {
       $summary[] = $this->t('Default labels are used.');
     }
 
+    if ($this->getSetting('revision')) {
+      $summary[] = $this->t('Create new revision');
+    }
+
     if ($this->getSetting('collapsible')) {
       $summary[] = $this->t($this->getSetting('collapsed') ? 'Collapsible, collapsed by default' : 'Collapsible');
     }
@@ -395,6 +405,7 @@ protected function getInlineEntityForm($operation, $bundle, $langcode, $delta, a
       '#default_value' => $entity,
       '#op' => $operation,
       '#form_mode' => $this->getSetting('form_mode'),
+      '#revision' => $this->getSetting('revision'),
       '#save_entity' => FALSE,
       '#ief_row_delta' => $delta,
       // Used by Field API and controller methods to find the relevant
diff --git a/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php b/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php
index b8424be3b6..a4b2c306b8 100644
--- a/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php
+++ b/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php
@@ -3,7 +3,10 @@
 namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
 
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Utility\Tags;
+use Drupal\Core\Entity\Element\EntityAutocomplete;
 use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
+use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -14,6 +17,7 @@
 use Drupal\Core\Render\Element;
 use Drupal\inline_entity_form\TranslationHelper;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Component\Utility\Crypt;
 
 /**
  * Complex inline widget.
@@ -22,7 +26,8 @@
  *   id = "inline_entity_form_complex",
  *   label = @Translation("Inline entity form - Complex"),
  *   field_types = {
- *     "entity_reference"
+ *     "entity_reference",
+ *     "entity_reference_revisions",
  *   },
  *   multiple_values = true
  * )
@@ -36,10 +41,17 @@ class InlineEntityFormComplex extends InlineEntityFormBase implements ContainerF
    */
   protected $moduleHandler;
 
+  /**
+   * Selection Plugin Manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface
+   */
+  protected $selectionManager;
+
   /**
    * Constructs a InlineEntityFormComplex object.
    *
-   * @param array $plugin_id
+   * @param string $plugin_id
    *   The plugin_id for the widget.
    * @param mixed $plugin_definition
    *   The plugin implementation definition.
@@ -57,10 +69,13 @@ class InlineEntityFormComplex extends InlineEntityFormBase implements ContainerF
    *   The entity display repository.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   Module handler service.
+   * @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface $selection_manager
+   *   The selection plugin manager.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository, ModuleHandlerInterface $module_handler) {
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository, ModuleHandlerInterface $module_handler, SelectionPluginManagerInterface $selection_manager) {
     parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $entity_type_bundle_info, $entity_type_manager, $entity_display_repository);
     $this->moduleHandler = $module_handler;
+    $this->selectionManager = $selection_manager;
   }
 
   /**
@@ -76,7 +91,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $container->get('entity_type.bundle.info'),
       $container->get('entity_type.manager'),
       $container->get('entity_display.repository'),
-      $container->get('module_handler')
+      $container->get('module_handler'),
+      $container->get('plugin.manager.entity_reference_selection')
     );
   }
 
@@ -198,9 +214,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     ]);
 
     // Assign a unique identifier to each IEF widget.
-    // Since $parents can get quite long, sha1() ensures that every id has
+    // Since $parents can get quite long, hashing ensures that every id has
     // a consistent and relatively short length while maintaining uniqueness.
-    $this->setIefId(sha1(implode('-', $parents)));
+    $this->setIefId(Crypt::hashBase64(implode('-', $parents)));
 
     // Get the langcode of the parent entity.
     $parent_langcode = $items->getEntity()->language()->getId();
@@ -226,8 +242,6 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       $element['#open'] = !$this->getSetting('collapsed');
     }
 
-    $element['#attached']['library'][] = 'inline_entity_form/widget';
-
     $this->prepareFormState($form_state, $items, $element['#translating']);
     $entities = $form_state->get(['inline_entity_form', $this->getIefId(), 'entities']);
 
@@ -510,6 +524,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       }
     }
     else {
+      // Make a delta key bigger than all existing ones, without assuming that
+      // the keys are strictly consecutive.
+      $new_key = $entities ? max(array_keys($entities)) + 1 : 0;
       // There's a form open, show it.
       if ($form_state->get(['inline_entity_form', $this->getIefId(), 'form']) == 'add') {
         $element['form'] = [
@@ -519,9 +536,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
             'add',
             $this->determineBundle($form_state),
             $parent_langcode,
-            NULL,
-            array_merge($parents, ['inline_entity_form'])
-          )
+            $new_key,
+            array_merge($parents, [$new_key])
+          ),
         ];
         $element['form']['inline_entity_form']['#process'] = [
           ['\Drupal\inline_entity_form\Element\InlineEntityForm', 'processEntityForm'],
@@ -537,7 +554,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
           '#ief_id' => $this->getIefId(),
           // Used by Field API and controller methods to find the relevant
           // values in $form_state.
-          '#parents' => array_merge($parents),
+          '#parents' => array_merge($parents, [$new_key]),
           '#entity_type' => $target_type,
           '#ief_labels' => $this->getEntityTypeLabels(),
           '#match_operator' => $this->getSetting('match_operator'),
@@ -583,7 +600,7 @@ public function extractFormValues(FieldItemListInterface $items, array $form, Fo
 
     $field_name = $this->fieldDefinition->getName();
     $parents = array_merge($form['#parents'], [$field_name, 'form']);
-    $ief_id = sha1(implode('-', $parents));
+    $ief_id = Crypt::hashBase64(implode('-', $parents));
     $this->setIefId($ief_id);
     $widget_state = &$form_state->get(['inline_entity_form', $ief_id]);
     foreach ($widget_state['entities'] as $key => $value) {
@@ -598,12 +615,68 @@ public function extractFormValues(FieldItemListInterface $items, array $form, Fo
     // If the inline entity form is still open, then its entity hasn't
     // been transferred to the IEF form state yet.
     if (empty($values) && !empty($widget_state['form'])) {
-      // @todo Do the same for reference forms.
       if ($widget_state['form'] == 'add') {
         $element = NestedArray::getValue($form, [$field_name, 'widget', 'form']);
         $entity = $element['inline_entity_form']['#entity'];
         $values[] = ['entity' => $entity];
       }
+      elseif ($widget_state['form'] == 'ief_add_existing') {
+        $parent = NestedArray::getValue($form, [$field_name, 'widget', 'form']);
+        $element = isset($parent['entity_id']) ? $parent['entity_id'] : [];
+        if (!empty($element['#value'])) {
+          $options = [
+            'target_type' => $element['#target_type'],
+            'handler' => $element['#selection_handler'],
+          ] + $element['#selection_settings'];
+          /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
+          $handler = $this->selectionManager->getInstance($options);
+          $input_values = $element['#tags'] ? Tags::explode($element['#value']) : [$element['#value']];
+
+          foreach ($input_values as $input) {
+            $match = EntityAutocomplete::extractEntityIdFromAutocompleteInput($input);
+            if ($match === NULL) {
+              // Try to get a match from the input string when the user didn't use
+              // the autocomplete but filled in a value manually.
+              $entities_by_bundle = $handler->getReferenceableEntities($input, '=');
+              $entities = array_reduce($entities_by_bundle, function ($flattened, $bundle_entities) {
+                return $flattened + $bundle_entities;
+              }, []);
+              $params = [
+                '%value' => $input,
+                '@value' => $input,
+              ];
+              if (empty($entities)) {
+                $form_state->setError($element, $this->t('There are no entities matching "%value".', $params));
+              }
+              elseif (count($entities) > 5) {
+                $params['@id'] = key($entities);
+                // Error if there are more than 5 matching entities.
+                $form_state->setError($element, $this->t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)".', $params));
+              }
+              elseif (count($entities) > 1) {
+                // More helpful error if there are only a few matching entities.
+                $multiples = [];
+                foreach ($entities as $id => $name) {
+                  $multiples[] = $name . ' (' . $id . ')';
+                }
+                $params['@id'] = $id;
+                $form_state->setError($element, $this->t('Multiple entities match this reference; "%multiple". Specify the one you want by appending the id in parentheses, like "@value (@id)".', ['%multiple' => implode('", "', $multiples)] + $params));
+              }
+              else {
+                // Take the one and only matching entity.
+                $values += [
+                  'target_id' => key($entities),
+                ];
+              }
+            }
+            else {
+              $values += [
+                'target_id' => $match,
+              ];
+            }
+          }
+        }
+      }
     }
     // Sort values by weight.
     uasort($values, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
@@ -809,9 +882,6 @@ public static function submitConfirmRemove($form, FormStateInterface $form_state
     $remove_button = $form_state->getTriggeringElement();
     $delta = $remove_button['#ief_row_delta'];
 
-    /** @var \Drupal\Core\Field\FieldDefinitionInterface $instance */
-    $instance = $form_state->get(['inline_entity_form', $element['#ief_id'], 'instance']);
-
     /** @var \Drupal\Core\Entity\EntityInterface $entity */
     $entity = $element['entities'][$delta]['form']['#entity'];
     $entity_id = $entity->id();
diff --git a/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php b/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
index 985e06bc6f..03eef594d2 100644
--- a/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
+++ b/web/modules/inline_entity_form/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Drupal\inline_entity_form\TranslationHelper;
+use Drupal\Component\Utility\Crypt;
 
 /**
  * Simple inline widget.
@@ -18,7 +19,8 @@
  *   id = "inline_entity_form_simple",
  *   label = @Translation("Inline entity form - Simple"),
  *   field_types = {
- *     "entity_reference"
+ *     "entity_reference",
+ *     "entity_reference_revisions",
  *   },
  *   multiple_values = false
  * )
@@ -32,7 +34,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     // Trick inline_entity_form_form_alter() into attaching the handlers,
     // WidgetSubmit will be needed once extractFormValues fills the $form_state.
     $parents = array_merge($element['#field_parents'], [$items->getName()]);
-    $ief_id = sha1(implode('-', $parents));
+    $ief_id = Crypt::hashBase64(implode('-', $parents));
     $form_state->set(['inline_entity_form', $ief_id], []);
 
     $element = [
@@ -85,9 +87,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
   protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
     $element = parent::formMultipleElements($items, $form, $form_state);
 
-    // If we're using ulimited cardinality we don't display one empty item. Form
-    // validation will kick in if left empty which esentially means people won't
-    // be able to submit w/o creating another entity.
+    // If we're using unlimited cardinality we don't display one empty item.
+    // Form validation will kick in if left empty which essentially means
+    // people won't be able to submit without creating another entity.
     if (!$form_state->isSubmitted() && $element['#cardinality'] == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && $element['#max_delta'] > 0) {
       $max = $element['#max_delta'];
       unset($element[$max]);
@@ -152,7 +154,7 @@ public function extractFormValues(FieldItemListInterface $items, array $form, Fo
 
     // Populate the IEF form state with $items so that WidgetSubmit can
     // perform the necessary saves.
-    $ief_id = sha1(implode('-', $parents));
+    $ief_id = Crypt::hashBase64(implode('-', $parents));
     $widget_state = [
       'instance' => $this->fieldDefinition,
       'delete' => [],
diff --git a/web/modules/inline_entity_form/src/Tests/ComplexSimpleWidgetTest.php b/web/modules/inline_entity_form/src/Tests/ComplexSimpleWidgetTest.php
deleted file mode 100644
index 115a8793d6..0000000000
--- a/web/modules/inline_entity_form/src/Tests/ComplexSimpleWidgetTest.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-
-namespace Drupal\inline_entity_form\Tests;
-
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-
-/**
- * IEF complex field widget containing an IEF simple field widget tests.
- *
- * @group inline_entity_form
- */
-class ComplexSimpleWidgetTest extends InlineEntityFormTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = [
-    'inline_entity_form_test',
-    'field',
-    'field_ui',
-  ];
-
-  protected function setUp() {
-    parent::setUp();
-
-    $this->user = $this->createUser([
-      'create ief_complex_simple content',
-      'create ief_simple_single content',
-      'create ief_test_custom content',
-      'view own unpublished content',
-    ]);
-    $this->drupalLogin($this->user);
-    $this->fieldConfigStorage = $this->container->get('entity_type.manager')->getStorage('field_config');
-  }
-
-  /**
-   * Test a Simple IEF widget inside of Complex IEF widget.
-   */
-  public function testSimpleInComplex() {
-    $outer_required_options = [
-      TRUE,
-      FALSE,
-    ];
-    $cardinality_options = [
-      1 => 1,
-      2 => 2,
-      FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => 3,
-    ];
-    /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
-    $field_storage = $this->fieldStorageConfigStorage->load('node.ief_complex_outer');
-    /** @var \Drupal\Core\Field\FieldConfigInterface $field_config */
-    $field_config = $this->fieldConfigStorage->load('node.ief_complex_simple.ief_complex_outer');
-    foreach ($outer_required_options as $outer_required_option) {
-      $edit = [];
-      $field_config->setRequired($outer_required_option);
-      $field_config->save();
-      foreach ($cardinality_options as $cardinality => $limit) {
-        $field_storage->setCardinality($cardinality);
-        $field_storage->save();
-
-        $this->drupalGet('node/add/ief_complex_simple');
-        $outer_title_field = 'ief_complex_outer[form][inline_entity_form][title][0][value]';
-        $inner_title_field = 'ief_complex_outer[form][inline_entity_form][single][0][inline_entity_form][title][0][value]';
-        if (!$outer_required_option) {
-          $this->assertText('Complex Outer', 'Complex Inline entity field widget title found.');
-          // Field should not be available before ajax submit.
-          $this->assertNoFieldByName($outer_title_field, NULL);
-          $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node" and @data-drupal-selector="edit-ief-complex-outer-actions-ief-add"]'));
-        }
-        $this->assertFieldByName($outer_title_field, NULL);
-        // Simple widget is required so should always show up. No need for add submit.
-        $this->assertFieldByName($inner_title_field, NULL);
-
-        $edit[$outer_title_field] = $outer_title = $this->randomMachineName(8);
-        $edit[$inner_title_field] = $inner_title = $this->randomMachineName(8);
-        $create_outer_button_selector = '//input[@type="submit" and @value="Create node" and @data-drupal-selector="edit-ief-complex-outer-form-inline-entity-form-actions-ief-add-save"]';
-        $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName($create_outer_button_selector));
-        // After ajax submit the ief title fields should be gone.
-        $this->assertNoFieldByName($outer_title_field, NULL);
-        $this->assertNoFieldByName($inner_title_field, NULL);
-        $this->assertEqual('', $this->getButtonName($create_outer_button_selector), 'Create node button not found after Ajax submit.');
-
-        // The nodes should not actually be saved at this point
-        $this->assertNoNodeByTitle($outer_title, 'Outer node was not created when widget submitted.');
-        $this->assertNoNodeByTitle($inner_title, 'Inner node was not created when widget submitted.');
-
-        $host_title = $this->randomMachineName(8);
-        $edit = ['title[0][value]' => $host_title];
-        $this->drupalPostForm(NULL, $edit, t('Save'));
-        $this->assertText("$host_title has been created.");
-        $this->assertText($outer_title);
-
-        // Check the nodes were created correctly.
-        $host_node = $this->drupalGetNodeByTitle($host_title);
-        if ($this->assertNotNull($host_node->ief_complex_outer->entity, 'Outer node was created.')) {
-          $outer_node = $host_node->ief_complex_outer->entity;
-          $this->assertEqual($outer_title, $outer_node->label(), "Outer node's title looks correct.");
-          $this->assertEqual('ief_simple_single', $outer_node->bundle(), "Outer node's type looks correct.");
-          if ($this->assertNotNull($outer_node->single->entity, 'Inner node was created')) {
-            $inner_node = $outer_node->single->entity;
-            $this->assertEqual($inner_title, $inner_node->label(), "Inner node's title looks correct.");
-            $this->assertEqual('ief_test_custom', $inner_node->bundle(), "Inner node's type looks correct.");
-          }
-        }
-      }
-    }
-  }
-
-}
diff --git a/web/modules/inline_entity_form/src/Tests/ComplexWidgetWebTest.php b/web/modules/inline_entity_form/src/Tests/ComplexWidgetWebTest.php
deleted file mode 100644
index d606c841b1..0000000000
--- a/web/modules/inline_entity_form/src/Tests/ComplexWidgetWebTest.php
+++ /dev/null
@@ -1,780 +0,0 @@
-<?php
-
-namespace Drupal\inline_entity_form\Tests;
-
-use Drupal\node\Entity\Node;
-
-/**
- * IEF complex field widget tests.
- *
- * @group inline_entity_form
- */
-class ComplexWidgetWebTest extends InlineEntityFormTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = [
-    'inline_entity_form_test',
-    'field',
-    'field_ui',
-  ];
-
-  /**
-   * URL to add new content.
-   *
-   * @var string
-   */
-  protected $formContentAddUrl;
-
-  /**
-   * Entity form display storage.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected $entityFormDisplayStorage;
-
-  /**
-   * Prepares environment for
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->user = $this->createUser([
-      'create ief_reference_type content',
-      'edit any ief_reference_type content',
-      'delete any ief_reference_type content',
-      'create ief_test_complex content',
-      'edit any ief_test_complex content',
-      'delete any ief_test_complex content',
-      'edit any ief_test_nested1 content',
-      'edit any ief_test_nested2 content',
-      'edit any ief_test_nested3 content',
-      'view own unpublished content',
-      'administer content types',
-    ]);
-    $this->drupalLogin($this->user);
-
-    $this->formContentAddUrl = 'node/add/ief_test_complex';
-    $this->entityFormDisplayStorage = $this->container->get('entity_type.manager')->getStorage('entity_form_display');
-  }
-
-  /**
-   * Tests if form behaves correctly when field is empty.
-   */
-  public function testEmptyFieldIEF() {
-    // Don't allow addition of existing nodes.
-    $this->updateSetting('allow_existing', FALSE);
-    $this->drupalGet($this->formContentAddUrl);
-
-    $this->assertFieldByName('multi[form][inline_entity_form][title][0][value]', NULL, 'Title field on inline form exists.');
-    $this->assertFieldByName('multi[form][inline_entity_form][first_name][0][value]', NULL, 'First name field on inline form exists.');
-    $this->assertFieldByName('multi[form][inline_entity_form][last_name][0][value]', NULL, 'Last name field on inline form exists.');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Create node"]', NULL, 'Found "Create node" submit button');
-
-    // Allow addition of existing nodes.
-    $this->updateSetting('allow_existing', TRUE);
-    $this->drupalGet($this->formContentAddUrl);
-
-    $this->assertNoFieldByName('multi[form][inline_entity_form][title][0][value]', NULL, 'Title field does not appear.');
-    $this->assertNoFieldByName('multi[form][inline_entity_form][first_name][0][value]', NULL, 'First name field does not appear.');
-    $this->assertNoFieldByName('multi[form][inline_entity_form][last_name][0][value]', NULL, 'Last name field does not appear.');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Add new node"]', NULL, 'Found "Add new node" submit button');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Add existing node"]', NULL, 'Found "Add existing node" submit button');
-
-    // Now submit 'Add new node' button.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node" and @data-drupal-selector="edit-multi-actions-ief-add"]'));
-
-    $this->assertFieldByName('multi[form][inline_entity_form][title][0][value]', NULL, 'Title field on inline form exists.');
-    $this->assertFieldByName('multi[form][inline_entity_form][first_name][0][value]', NULL, 'First name field on inline form exists.');
-    $this->assertFieldByName('multi[form][inline_entity_form][last_name][0][value]', NULL, 'Second name field on inline form exists.');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Create node"]', NULL, 'Found "Create node" submit button');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Cancel"]', NULL, 'Found "Cancel" submit button');
-
-    // Now submit 'Add Existing node' button.
-    $this->drupalGet($this->formContentAddUrl);
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add existing node" and @data-drupal-selector="edit-multi-actions-ief-add-existing"]'));
-
-    $this->assertFieldByName('multi[form][entity_id]', NULL, 'Existing entity reference autocomplete field found.');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Add node"]', NULL, 'Found "Add node" submit button');
-    $this->assertFieldByXpath('//input[@type="submit" and @value="Cancel"]', NULL, 'Found "Cancel" submit button');
-  }
-
-  /**
-   * Tests creation of entities.
-   */
-  public function testEntityCreation() {
-    // Allow addition of existing nodes.
-    $this->updateSetting('allow_existing', TRUE);
-    $this->drupalGet($this->formContentAddUrl);
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node" and @data-drupal-selector="edit-multi-actions-ief-add"]'));
-    $this->assertResponse(200, 'Opening new inline form was successful.');
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Create node" and @data-drupal-selector="edit-multi-form-inline-entity-form-actions-ief-add-save"]'));
-    $this->assertResponse(200, 'Submitting empty form was successful.');
-    $this->assertText('First name field is required.', 'Validation failed for empty "First name" field.');
-    $this->assertText('Last name field is required.', 'Validation failed for empty "Last name" field.');
-    $this->assertText('Title field is required.', 'Validation failed for empty "Title" field.');
-
-    // Create ief_reference_type node in IEF.
-    $this->drupalGet($this->formContentAddUrl);
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node" and @data-drupal-selector="edit-multi-actions-ief-add"]'));
-    $this->assertResponse(200, 'Opening new inline form was successful.');
-
-    $edit = [
-      'multi[form][inline_entity_form][title][0][value]' => 'Some reference',
-      'multi[form][inline_entity_form][first_name][0][value]' => 'John',
-      'multi[form][inline_entity_form][last_name][0][value]' => 'Doe',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Create node" and @data-drupal-selector="edit-multi-form-inline-entity-form-actions-ief-add-save"]'));
-    $this->assertResponse(200, 'Creating node via inline form was successful.');
-
-    // Tests if correct fields appear in the table.
-    $this->assertTrue((bool) $this->xpath('//td[@class="inline-entity-form-node-label" and contains(.,"Some reference")]'), 'Node title field appears in the table');
-    $this->assertTrue((bool) $this->xpath('//td[@class="inline-entity-form-node-status" and ./div[contains(.,"Published")]]'), 'Node status field appears in the table');
-
-    // Tests if edit and remove buttons appear.
-    $this->assertTrue((bool) $this->xpath('//input[@type="submit" and @value="Edit"]'), 'Edit button appears in the table.');
-    $this->assertTrue((bool) $this->xpath('//input[@type="submit" and @value="Remove"]'), 'Remove button appears in the table.');
-
-    // Test edit functionality.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Edit"]'));
-    $edit = [
-      'multi[form][inline_entity_form][entities][0][form][title][0][value]' => 'Some changed reference',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Update node"]'));
-    $this->assertTrue((bool) $this->xpath('//td[@class="inline-entity-form-node-label" and contains(.,"Some changed reference")]'), 'Node title field appears in the table');
-    $this->assertTrue((bool) $this->xpath('//td[@class="inline-entity-form-node-status" and ./div[contains(.,"Published")]]'), 'Node status field appears in the table');
-
-    // Make sure unrelated AJAX submit doesn't save the referenced entity.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Upload"]'));
-    $node = $this->drupalGetNodeByTitle('Some changed reference');
-    $this->assertFalse($node, 'Referenced node was not saved during unrelated AJAX submit.');
-
-    // Create ief_test_complex node.
-    $edit = ['title[0][value]' => 'Some title'];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertResponse(200, 'Saving parent entity was successful.');
-
-    // Checks values of created entities.
-    $node = $this->drupalGetNodeByTitle('Some changed reference');
-    $this->assertTrue($node, 'Created ief_reference_type node ' . $node->label());
-    $this->assertTrue($node->get('first_name')->value == 'John', 'First name in reference node set to John');
-    $this->assertTrue($node->get('last_name')->value == 'Doe', 'Last name in reference node set to Doe');
-
-    $parent_node = $this->drupalGetNodeByTitle('Some title');
-    $this->assertTrue($parent_node, 'Created ief_test_complex node ' . $parent_node->label());
-    $this->assertTrue($parent_node->multi->target_id == $node->id(), 'Refererence node id set to ' . $node->id());
-  }
-
-  /**
-   * Tests the entity creation with different bundles nested in each other.
-   *
-   * ief_test_nested1 -> ief_test_nested2 -> ief_test_nested3
-   */
-  public function testNestedEntityCreationWithDifferentBundlesAjaxSubmit() {
-    $required_possibilities = [
-      FALSE,
-      TRUE,
-    ];
-    foreach ($required_possibilities as $required) {
-      $this->setupNestedComplexForm($required);
-
-      $nested3_title = 'nested3 title steps ' . ($required ? 'required' : 'not required');
-      $nested2_title = 'nested2 title steps ' . ($required ? 'required' : 'not required');
-      $nested1_title = 'nested1 title steps ' . ($required ? 'required' : 'not required');
-      $edit = [
-        'test_ref_nested1[form][inline_entity_form][test_ref_nested2][form][inline_entity_form][title][0][value]' => $nested3_title,
-      ];
-      $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Create node 3"]'));
-      $this->assertText($nested3_title, 'Title of second nested node found.');
-      $this->assertNoNodeByTitle($nested3_title, 'Second nested entity is not saved yet.');
-
-      $edit = [
-        'test_ref_nested1[form][inline_entity_form][title][0][value]' => $nested2_title,
-      ];
-      $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Create node 2"]'));
-      $this->assertText($nested2_title, 'Title of first nested node found.');
-      $this->assertNoNodeByTitle($nested2_title, 'First nested entity is not saved yet.');
-
-      $edit = [
-        'title[0][value]' => $nested1_title,
-      ];
-      $this->drupalPostForm(NULL, $edit, t('Save'));
-      $this->checkNestedNodes($nested1_title, $nested2_title, $nested3_title);
-    }
-  }
-
-  /**
-   * Checks that nested IEF entity references can be edit and saved.
-   *
-   * @param \Drupal\node\Entity\Node $node
-   *   Top level node of type ief_test_nested1 to check.
-   * @param bool $ajax_submit
-   *   Whether IEF form widgets should be submitted via AJAX or left open.
-   */
-  protected function checkNestedEntityEditing(Node $node, $ajax_submit = TRUE) {
-    $this->drupalGet("node/{$node->id()}/edit");
-    /** @var \Drupal\node\Entity\Node $level_1_node */
-    $level_1_node = $node->test_ref_nested1->entity;
-    /** @var \Drupal\node\Entity\Node $level_2_node */
-    $level_2_node = $node->test_ref_nested1->entity->test_ref_nested2->entity;
-    $level_2_node_update_title = $level_2_node->getTitle() . ' - updated';
-    // edit-test-ref-nested1-entities-0-actions-ief-entity-edit
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-test-ref-nested1-entities-0-actions-ief-entity-edit"]'));
-    // edit-test-ref-nested1-form-inline-entity-form-entities-0-form-test-ref-nested2-entities-0-actions-ief-entity-edit
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-test-ref-nested1-form-inline-entity-form-entities-0-form-test-ref-nested2-entities-0-actions-ief-entity-edit"]'));
-    $edit['test_ref_nested1[form][inline_entity_form][entities][0][form][test_ref_nested2][form][inline_entity_form][entities][0][form][title][0][value]'] = $level_2_node_update_title;
-    if ($ajax_submit) {
-      // Close IEF Forms with AJAX posts
-      // edit-test-ref-nested1-form-inline-entity-form-entities-0-form-test-ref-nested2-form-inline-entity-form-entities-0-form-actions-ief-edit-save
-      $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-test-ref-nested1-form-inline-entity-form-entities-0-form-test-ref-nested2-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]'));
-      $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-test-ref-nested1-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]'));
-      $this->drupalPostForm(NULL, [], t('Save'));
-    }
-    else {
-      $this->drupalPostForm(NULL, $edit, t('Save'));
-    }
-    $this->nodeStorage->resetCache([$level_2_node->id()]);
-    $level_2_node = $this->nodeStorage->load($level_2_node->id());
-    $this->assertEqual($level_2_node_update_title, $level_2_node->getTitle());
-  }
-
-  /**
-   * Tests the entity creation with different bundles nested in each other.
-   *
-   * ief_test_nested1 -> ief_test_nested2 -> ief_test_nested3
-   */
-  public function testNestedEntityCreationWithDifferentBundlesNoAjaxSubmit() {
-    $required_possibilities = [
-      FALSE,
-      TRUE,
-    ];
-
-    foreach ($required_possibilities as $required) {
-      $this->setupNestedComplexForm($required);
-
-      $nested3_title = 'nested3 title single ' . ($required ? 'required' : 'not required');
-      $nested2_title = 'nested2 title single ' . ($required ? 'required' : 'not required');
-      $nested1_title = 'nested1 title single ' . ($required ? 'required' : 'not required');
-
-      $edit = [
-        'title[0][value]' => $nested1_title,
-        'test_ref_nested1[form][inline_entity_form][title][0][value]' => $nested2_title,
-        'test_ref_nested1[form][inline_entity_form][test_ref_nested2][form][inline_entity_form][title][0][value]' => $nested3_title,
-      ];
-      $this->drupalPostForm(NULL, $edit, t('Save'));
-      $this->checkNestedNodes($nested1_title, $nested2_title, $nested3_title);
-    }
-  }
-
-  /**
-   * Tests if editing and removing entities work.
-   */
-  public function testEntityEditingAndRemoving() {
-    // Allow addition of existing nodes.
-    $this->updateSetting('allow_existing', TRUE);
-
-    // Create three ief_reference_type entities.
-    $referenceNodes = $this->createReferenceContent(3);
-    $this->drupalCreateNode([
-      'type' => 'ief_test_complex',
-      'title' => 'Some title',
-      'multi' => array_values($referenceNodes),
-    ]);
-    /** @var \Drupal\node\NodeInterface $node */
-    $parent_node = $this->drupalGetNodeByTitle('Some title');
-
-    // Edit the second entity.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    $cell = $this->xpath('//table[@id="ief-entity-table-edit-multi-entities"]/tbody/tr[@class="ief-row-entity draggable even"]/td[@class="inline-entity-form-node-label"]');
-    $title = (string) $cell[0];
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @id="edit-multi-entities-1-actions-ief-entity-edit"]'));
-    $this->assertResponse(200, 'Opening inline edit form was successful.');
-
-    $edit = [
-      'multi[form][inline_entity_form][entities][1][form][first_name][0][value]' => 'John',
-      'multi[form][inline_entity_form][entities][1][form][last_name][0][value]' => 'Doe',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-inline-entity-form-entities-1-form-actions-ief-edit-save"]'));
-    $this->assertResponse(200, 'Saving inline edit form was successful.');
-
-    // Save the ief_test_complex node.
-    $this->drupalPostForm(NULL, [], t('Save'));
-    $this->assertResponse(200, 'Saving parent entity was successful.');
-
-    // Checks values of changed entities.
-    $node = $this->drupalGetNodeByTitle($title, TRUE);
-    $this->assertTrue($node->first_name->value == 'John', 'First name in reference node changed to John');
-    $this->assertTrue($node->last_name->value == 'Doe', 'Last name in reference node changed to Doe');
-
-    // Delete the second entity.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    $cell = $this->xpath('//table[@id="ief-entity-table-edit-multi-entities"]/tbody/tr[@class="ief-row-entity draggable even"]/td[@class="inline-entity-form-node-label"]');
-    $title = (string) $cell[0];
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @id="edit-multi-entities-1-actions-ief-entity-remove"]'));
-    $this->assertResponse(200, 'Opening inline remove confirm form was successful.');
-    $this->assertText('Are you sure you want to remove', 'Remove warning message is displayed.');
-
-    $this->drupalPostAjaxForm(NULL, ['multi[form][entities][1][form][delete]' => TRUE], $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-entities-1-form-actions-ief-remove-confirm"]'));
-    $this->assertResponse(200, 'Removing inline entity was successful.');
-    $this->assertNoText($title, 'Deleted inline entity is not present on the page.');
-
-    // Save the ief_test_complex node.
-    $this->drupalPostForm(NULL, [], t('Save'));
-    $this->assertResponse(200, 'Saving parent node was successful.');
-
-    $deleted_node = $this->drupalGetNodeByTitle($title);
-    $this->assertTrue(empty($deleted_node), 'The inline entity was deleted from the site.');
-
-    // Checks that entity does nor appear in IEF.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    $this->assertNoText($title, 'Deleted inline entity is not present on the page after saving parent.');
-
-    // Delete the third entity reference only, don't delete the node. The third
-    // entity now is second referenced entity because the second one was deleted
-    // in previous step.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    $cell = $this->xpath('//table[@id="ief-entity-table-edit-multi-entities"]/tbody/tr[@class="ief-row-entity draggable even"]/td[@class="inline-entity-form-node-label"]');
-    $title = (string) $cell[0];
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @id="edit-multi-entities-1-actions-ief-entity-remove"]'));
-    $this->assertResponse(200, 'Opening inline remove confirm form was successful.');
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-entities-1-form-actions-ief-remove-confirm"]'));
-    $this->assertResponse(200, 'Removing inline entity was successful.');
-
-    // Save the ief_test_complex node.
-    $this->drupalPostForm(NULL, [], t('Save'));
-    $this->assertResponse(200, 'Saving parent node was successful.');
-
-    // Checks that entity does nor appear in IEF.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    $this->assertNoText($title, 'Deleted inline entity is not present on the page after saving parent.');
-
-    // Checks that entity is not deleted.
-    $node = $this->drupalGetNodeByTitle($title, TRUE);
-    $this->assertTrue($node, 'Reference node not deleted');
-  }
-
-  /**
-   * Tests if referencing existing entities work.
-   */
-  public function testReferencingExistingEntities() {
-    // Allow addition of existing nodes.
-    $this->updateSetting('allow_existing', TRUE);
-
-    // Create three ief_reference_type entities.
-    $referenceNodes = $this->createReferenceContent(3);
-
-    // Create a node for every bundle available.
-    $bundle_nodes = $this->createNodeForEveryBundle();
-
-    // Create ief_test_complex node with first ief_reference_type node and first
-    // node from bundle nodes.
-    $this->drupalCreateNode([
-      'type' => 'ief_test_complex',
-      'title' => 'Some title',
-      'multi' => [1],
-      'all_bundles' => key($bundle_nodes),
-    ]);
-    // Remove first node since we already added it.
-    unset($bundle_nodes[key($bundle_nodes)]);
-
-    $parent_node = $this->drupalGetNodeByTitle('Some title', TRUE);
-
-    // Add remaining existing reference nodes.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    for ($i = 2; $i <= 3; $i++) {
-      $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add existing node" and @data-drupal-selector="edit-multi-actions-ief-add-existing"]'));
-      $this->assertResponse(200, 'Opening reference form was successful.');
-      $title = 'Some reference ' . $i;
-      $edit = [
-        'multi[form][entity_id]' => $title . ' (' . $referenceNodes[$title] . ')',
-      ];
-      $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-actions-ief-reference-save"]'));
-      $this->assertResponse(200, 'Adding new referenced entity was successful.');
-    }
-    // Add all remaining nodes from all bundles.
-    foreach ($bundle_nodes as $id => $title) {
-      $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add existing node" and @data-drupal-selector="edit-all-bundles-actions-ief-add-existing"]'));
-      $this->assertResponse(200, 'Opening reference form was successful.');
-      $edit = [
-        'all_bundles[form][entity_id]' => $title . ' (' . $id . ')',
-      ];
-      $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-all-bundles-form-actions-ief-reference-save"]'));
-      $this->assertResponse(200, 'Adding new referenced entity was successful.');
-    }
-    // Save the node.
-    $this->drupalPostForm(NULL, [], t('Save'));
-    $this->assertResponse(200, 'Saving parent for was successful.');
-
-    // Check if entities are referenced.
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    for ($i = 2; $i <= 3; $i++) {
-      $cell = $this->xpath('//table[@id="ief-entity-table-edit-multi-entities"]/tbody/tr[' . $i . ']/td[@class="inline-entity-form-node-label"]');
-      $this->assertTrue($cell[0] == 'Some reference ' . $i, 'Found reference node title "Some reference ' . $i . '" in the IEF table.');
-    }
-    // Check if all remaining nodes from all bundles are referenced.
-    $count = 2;
-    foreach ($bundle_nodes as $id => $title) {
-      $cell = $this->xpath('//table[@id="ief-entity-table-edit-all-bundles-entities"]/tbody/tr[' . $count . ']/td[@class="inline-entity-form-node-label"]');
-      $this->assertTrue($cell[0] == $title, 'Found reference node title "' . $title . '" in the IEF table.');
-      $count++;
-    }
-  }
-
-  /**
-   * Test if invalid values get correct validation messages in reference existing entity form.
-   *
-   * Also checks if existing entity reference form can be canceled.
-   */
-  public function testReferenceExistingValidation() {
-    $this->updateSetting('allow_existing', TRUE);
-
-    $this->drupalGet('node/add/ief_test_complex');
-    $this->checkExistingValidationExpectation('', 'Node field is required.');
-    $this->checkExistingValidationExpectation('Fake Title', "There are no entities matching \"Fake Title\"");
-    // Check adding nodes that cannot be referenced by this field.
-    $bundle_nodes = $this->createNodeForEveryBundle();
-    foreach ($bundle_nodes as $id => $title) {
-      $node = $this->nodeStorage->load($id);
-      if ($node->bundle() != 'ief_reference_type') {
-        $this->checkExistingValidationExpectation("$title ($id)", "The referenced entity (node: $id) does not exist.");
-      }
-    }
-
-    $nodes = $this->createReferenceContent(2);
-    foreach ($nodes as $title => $id) {
-      $this->openMultiExistingForm();
-      $edit = [
-        'multi[form][entity_id]' => "$title ($id)",
-      ];
-      // Add a node successfully.
-      $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-actions-ief-reference-save"]'));
-      $this->assertNoFieldByName('multi[form][entity_id]', NULL, 'Existing entity reference autocomplete field removed.');
-      // Try to add the same node again.
-      $this->checkExistingValidationExpectation("$title ($id)", 'The selected node has already been added.');
-    }
-  }
-
-  /**
-   * Tests if duplicating entities works.
-   */
-  public function testDuplicatingEntities() {
-    $this->updateSetting('allow_duplicate', TRUE);
-
-    $referenceNodes = $this->createReferenceContent(2);
-    $this->drupalCreateNode([
-      'type' => 'ief_test_complex',
-      'title' => 'Some title',
-      'multi' => array_values($referenceNodes),
-    ]);
-    /** @var \Drupal\node\NodeInterface $node */
-    $parent_node = $this->drupalGetNodeByTitle('Some title');
-
-    $this->drupalGet('node/' . $parent_node->id() . '/edit');
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @id="edit-multi-entities-0-actions-ief-entity-duplicate"]'));
-    $this->assertResponse(200, 'Opening inline duplicate form was successful.');
-
-    $edit = [
-      'multi[form][inline_entity_form][entities][0][form][title][0][value]' => 'Duplicate!',
-      'multi[form][inline_entity_form][entities][0][form][first_name][0][value]' => 'Bojan',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-inline-entity-form-entities-0-form-actions-ief-duplicate-save"]'));
-    $this->assertResponse(200, 'Saving inline duplicate form was successful.');
-
-    $this->assertText('Some reference 1');
-    $this->assertText('Some reference 2');
-    $this->assertText('Duplicate!');
-    $this->drupalPostForm(NULL, [], t('Save'));
-    $this->assertResponse(200, 'Saving parent entity was successful.');
-
-    // Confirm a duplicate was made.
-    $duplicate = Node::load(4);
-    $this->assertEqual($duplicate->label(), 'Duplicate!');
-    $this->assertEqual($duplicate->first_name->value, 'Bojan');
-  }
-
-  /**
-   * Tests if a referenced content can be edited while the referenced content is
-   * newer than the referencing parent node.
-   */
-  public function testEditedInlineEntityValidation() {
-    $this->updateSetting('allow_existing', TRUE);
-
-    // Create referenced content.
-    $referenced_nodes = $this->createReferenceContent(1);
-
-    // Create first referencing node.
-    $this->drupalCreateNode([
-      'type' => 'ief_test_complex',
-      'title' => 'First referencing node',
-      'multi' => array_values($referenced_nodes),
-    ]);
-    $first_node = $this->drupalGetNodeByTitle('First referencing node');
-
-    // Create second referencing node.
-    $this->drupalCreateNode([
-      'type' => 'ief_test_complex',
-      'title' => 'Second referencing node',
-      'multi' => array_values($referenced_nodes),
-    ]);
-    $second_node = $this->drupalGetNodeByTitle('Second referencing node');
-
-    // Edit referenced content in first node.
-    $this->drupalGet('node/' . $first_node->id() . '/edit');
-
-    // Edit referenced node.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Edit" and @data-drupal-selector="edit-multi-entities-0-actions-ief-entity-edit"]'));
-    $edit = [
-      'multi[form][inline_entity_form][entities][0][form][title][0][value]' => 'Some reference updated',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Update node" and @data-drupal-selector="edit-multi-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]'));
-
-    // Save the first node after editing the reference.
-    $edit = ['title[0][value]' => 'First node updated'];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-
-    // The changed value of the referenced content is now newer than the
-    // changed value of the second node.
-
-    // Edit referenced content in second node.
-    $this->drupalGet('node/' . $second_node->id() . '/edit');
-
-    // Edit referenced node.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Edit" and @data-drupal-selector="edit-multi-entities-0-actions-ief-entity-edit"]'));
-    $edit = [
-      'multi[form][inline_entity_form][entities][0][form][title][0][value]' => 'Some reference updated the second time',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Update node" and @data-drupal-selector="edit-multi-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]'));
-
-    // Save the second node after editing the reference.
-    $edit = ['title[0][value]' => 'Second node updated'];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-
-    // Check if the referenced content could be edited.
-    $this->assertNoText('The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.', 'The referenced content could be edited.');
-  }
-
-  /**
-   * Creates ief_reference_type nodes which shall serve as reference nodes.
-   *
-   * @param int $numNodes
-   *   The number of nodes to create
-   * @return array
-   *   Array of created node ids keyed by labels.
-   */
-  protected function createReferenceContent($numNodes = 3) {
-    $retval = [];
-    for ($i = 1; $i <= $numNodes; $i++) {
-      $this->drupalCreateNode([
-        'type' => 'ief_reference_type',
-        'title' => 'Some reference ' . $i,
-        'first_name' => 'First Name ' . $i,
-        'last_name' => 'Last Name ' . $i,
-      ]);
-      $node = $this->drupalGetNodeByTitle('Some reference ' . $i);
-      $this->assertTrue($node, 'Created ief_reference_type node "' . $node->label() . '"');
-      $retval[$node->label()] = $node->id();
-    }
-    return $retval;
-  }
-
-  /**
-   * Updates an IEF setting and saves the underlying entity display.
-   *
-   * @param string $name
-   *   The name of the setting.
-   * @param mixed $value
-   *   The value to set.
-   */
-  protected function updateSetting($name, $value) {
-    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */
-    $display = $this->entityFormDisplayStorage->load('node.ief_test_complex.default');
-    $component = $display->getComponent('multi');
-    $component['settings'][$name] = $value;
-    $display->setComponent('multi', $component)->save();
-  }
-
-  /**
-   * Creates a node for every node bundle.
-   *
-   * @return array
-   *   Array of node titles keyed by ids.
-   */
-  protected function createNodeForEveryBundle() {
-    $retval = [];
-    $bundles = $this->container->get('entity.manager')->getBundleInfo('node');
-    foreach ($bundles as $id => $value) {
-      $this->drupalCreateNode(['type' => $id, 'title' => $value['label']]);
-      $node = $this->drupalGetNodeByTitle($value['label']);
-      $this->assertTrue($node, 'Created node "' . $node->label() . '"');
-      $retval[$node->id()] = $value['label'];
-    }
-    return $retval;
-  }
-
-  /**
-   * Set up the ief_test_nested1 node add form.
-   *
-   * Sets the nested fields' required settings.
-   * Gets the form.
-   * Opens the inline entity forms if they are not required.
-   *
-   * @param bool $required
-   *   Whether the fields are required.
-   * @param array $permissions
-   *   (optional) Permissions to sign testing user in with. You may pass in an
-   *   empty array (default) to use the all the permissions necessary create and
-   *   edit nodes on the form.
-   */
-  protected function setupNestedComplexForm($required, $permissions = []) {
-    /** @var \Drupal\Core\Field\FieldConfigInterface $ief_test_nested1 */
-    $ief_test_nested1 = $this->fieldConfigStorage->load('node.ief_test_nested1.test_ref_nested1');
-    $ief_test_nested1->setRequired($required);
-    $ief_test_nested1->save();
-    /** @var \Drupal\Core\Field\FieldConfigInterface $ief_test_nested2 */
-    $ief_test_nested2 = $this->fieldConfigStorage->load('node.ief_test_nested2.test_ref_nested2');
-    $ief_test_nested2->setRequired($required);
-    $ief_test_nested2->save();
-
-    if (!$permissions) {
-      $permissions = [
-        'create ief_test_nested1 content',
-        'create ief_test_nested2 content',
-        'create ief_test_nested3 content',
-        'edit any ief_test_nested1 content',
-        'edit any ief_test_nested2 content',
-        'edit any ief_test_nested3 content',
-      ];
-    }
-    $this->user = $this->createUser($permissions);
-    $this->drupalLogin($this->user);
-
-    $this->drupalGet('node/add/ief_test_nested1');
-
-    if (!$required) {
-      // Open inline forms if not required.
-      if (in_array('create ief_test_nested2 content', $permissions)) {
-        $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node 2"]'));
-      }
-      if (in_array('create ief_test_nested3 content', $permissions)) {
-        $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node 3"]'));
-      }
-    }
-  }
-
-  /**
-   * Closes the existing node form on the "multi" field.
-   */
-  protected function cancelExistingMultiForm($edit) {
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-actions-ief-reference-cancel"]'));
-    $this->assertNoFieldByName('multi[form][entity_id]', NULL, 'Existing entity reference autocomplete field removed.');
-  }
-
-  /**
-   * Opens the existing node form on the "multi" field.
-   */
-  protected function openMultiExistingForm() {
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add existing node" and @data-drupal-selector="edit-multi-actions-ief-add-existing"]'));
-    $this->assertResponse(200, 'Opening reference form was successful.');
-    $this->assertFieldByName('multi[form][entity_id]', NULL, 'Existing entity reference autocomplete field found.');
-  }
-
-  /**
-   * Checks that an invalid value for an existing node will be display the expected error.
-   *
-   * @param $existing_node_text
-   *   The text to enter into the existing node text field.
-   * @param $expected_error
-   *   The error message that is expected to be shown.
-   */
-  protected function checkExistingValidationExpectation($existing_node_text, $expected_error) {
-    $edit = [
-      'multi[form][entity_id]' => $existing_node_text,
-    ];
-    $this->openMultiExistingForm();
-
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-actions-ief-reference-save"]'));
-    $this->assertText($expected_error);
-    $this->cancelExistingMultiForm($edit);
-  }
-
-  /**
-   * Tests entity create access is correct on nested IEF forms.
-   */
-  public function testNestedEntityCreateAccess() {
-    $permissions = [
-      'create ief_test_nested1 content',
-      'create ief_test_nested2 content',
-    ];
-    $this->setupNestedComplexForm(TRUE, $permissions);
-    $this->assertFieldByName('title[0][value]');
-    $this->assertFieldByName('test_ref_nested1[form][inline_entity_form][title][0][value]');
-    $this->assertNoFieldByName('test_ref_nested1[form][inline_entity_form][test_ref_nested2][form][inline_entity_form][title][0][value]', NULL);
-
-    $this->setupNestedComplexForm(FALSE, $permissions);
-    $this->assertNoFieldByXPath('//input[@type="submit" and @value="Add new node 3"]');
-  }
-
-  /**
-   * Tests create access on IEF Complex content type.
-   */
-  public function testComplexEntityCreate() {
-    $user = $this->createUser([
-      'create ief_test_complex content',
-    ]);
-    $this->drupalLogin($user);
-
-    $this->drupalGet('node/add/ief_test_complex');
-    $this->assertNoFieldByName('all_bundles[actions][bundle]', NULL, 'Bundle select is not shown when only one bundle is available.');
-    $this->assertNoFieldByName('multi[form][inline_entity_form][title][0][value]', NULL);
-
-    $user = $this->createUser([
-      'create ief_test_complex content',
-      'create ief_reference_type content'
-    ]);
-    $this->drupalLogin($user);
-
-    $this->drupalGet('node/add/ief_test_complex');
-    $this->assertFieldByName('all_bundles[actions][bundle]', NULL, 'Bundle select is shown when more than one bundle is available.');
-    $this->assertOption('edit-all-bundles-actions-bundle', 'ief_reference_type');
-    $this->assertOption('edit-all-bundles-actions-bundle', 'ief_test_complex');
-    $this->assertFieldByName('multi[form][inline_entity_form][title][0][value]');
-  }
-
-  /**
-   * Checks if nested nodes for ief_test_nested1 content were created correctly.
-   *
-   * @param $nested1_title
-   *   Expected title of top level node of the type ief_test_nested1
-   * @param $nested2_title
-   *   Expected title of second level node
-   * @param $nested3_title
-   *   Expected title of third level node
-   */
-  protected function checkNestedNodes($nested1_title, $nested2_title, $nested3_title) {
-    $nested1_node = $this->drupalGetNodeByTitle($nested1_title);
-    $this->assertEqual($nested1_title, $nested1_node->label(), "First node's title looks correct.");
-    $this->assertEqual('ief_test_nested1', $nested1_node->bundle(), "First node's type looks correct.");
-    if ($this->assertNotNull($nested1_node->test_ref_nested1->entity, 'Second node was created.')) {
-      $this->assertEqual($nested1_node->test_ref_nested1->count(), 1, 'Only 1 node created at first level.');
-      $this->assertEqual($nested2_title, $nested1_node->test_ref_nested1->entity->label(), "Second node's title looks correct.");
-      $this->assertEqual('ief_test_nested2', $nested1_node->test_ref_nested1->entity->bundle(), "Second node's type looks correct.");
-      if ($this->assertNotNull($nested1_node->test_ref_nested1->entity->test_ref_nested2->entity, 'Third node was created')) {
-        $this->assertEqual($nested1_node->test_ref_nested1->entity->test_ref_nested2->count(), 1, 'Only 1 node created at second level.');
-        $this->assertEqual($nested3_title, $nested1_node->test_ref_nested1->entity->test_ref_nested2->entity->label(), "Third node's title looks correct.");
-        $this->assertEqual('ief_test_nested3', $nested1_node->test_ref_nested1->entity->test_ref_nested2->entity->bundle(), "Third node's type looks correct.");
-
-        $this->checkNestedEntityEditing($nested1_node, TRUE);
-      }
-    }
-  }
-
-}
diff --git a/web/modules/inline_entity_form/src/Tests/ElementWebTest.php b/web/modules/inline_entity_form/src/Tests/ElementWebTest.php
deleted file mode 100644
index 44686e884c..0000000000
--- a/web/modules/inline_entity_form/src/Tests/ElementWebTest.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-namespace Drupal\inline_entity_form\Tests;
-
-/**
- * Tests the IEF element on a custom form.
- *
- * @group inline_entity_form
- */
-class ElementWebTest extends InlineEntityFormTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['inline_entity_form_test'];
-
-  /**
-   * Prepares environment for
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->user = $this->createUser([
-      'create ief_simple_single content',
-      'edit any ief_test_custom content',
-      'view own unpublished content',
-      'administer nodes',
-    ]);
-
-    $this->drupalLogin($this->user);
-
-    $this->fieldStorageConfigStorage = $this->container->get('entity_type.manager')->getStorage('field_storage_config');
-  }
-
-  /**
-   * Tests IEF on a custom form.
-   */
-  public function testCustomFormIEF() {
-    $form_mode_possibilities = [
-      'default',
-      'inline',
-    ];
-    foreach ($form_mode_possibilities as $form_mode_possibility) {
-      $title = $this->randomMachineName();
-      $this->drupalGet("ief-test/$form_mode_possibility");
-      $this->assertText(t('Title'), 'Title field found on the form.');
-      $this->assertText(t('Positive int'), 'Positive int field found on form.');
-      $this->checkFormDisplayFields("node.ief_test_custom.$form_mode_possibility", 'inline_entity_form');
-
-      $edit = [];
-      $this->drupalPostForm('ief-test', $edit, t('Save'));
-      $this->assertText('Title field is required.');
-      $this->assertNoNodeByTitle($title);
-
-      $edit['inline_entity_form[title][0][value]'] = $title;
-      $edit['inline_entity_form[positive_int][0][value]'] = -1;
-      $this->drupalPostForm('ief-test', $edit, t('Save'));
-      $this->assertText('Positive int must be higher than or equal to 1');
-      $this->assertNoNodeByTitle($title);
-
-      $edit['inline_entity_form[positive_int][0][value]'] = 11;
-      $this->drupalPostForm('ief-test', $edit, t('Save'));
-      $message = t('Created @entity_type @label.', ['@entity_type' => t('Content'), '@label' => $edit['inline_entity_form[title][0][value]']]);
-      $this->assertText($message, 'Status message found on the page.');
-      $this->assertNodeByTitle($title, 'ief_test_custom');
-
-      if ($node = $this->getNodeByTitle($title)) {
-        $this->drupalGet("ief-test/$form_mode_possibility/{$node->id()}");
-        $this->assertFieldByName('inline_entity_form[title][0][value]', $title, 'Node title appears in form.');
-        $this->checkFormDisplayFields("node.ief_test_custom.$form_mode_possibility", 'inline_entity_form');
-        $this->assertFieldByName('inline_entity_form[positive_int][0][value]', 11, 'Positive int field appears in form.');
-        $updated_title = $title . ' - updated';
-        $edit['inline_entity_form[title][0][value]'] = $updated_title;
-        $this->drupalPostForm(NULL, $edit, t('Update'));
-        $this->assertNodeByTitle($updated_title, 'ief_test_custom');
-      }
-    }
-  }
-
-}
diff --git a/web/modules/inline_entity_form/src/Tests/InlineEntityFormTestBase.php b/web/modules/inline_entity_form/src/Tests/InlineEntityFormTestBase.php
deleted file mode 100644
index d3a399f05e..0000000000
--- a/web/modules/inline_entity_form/src/Tests/InlineEntityFormTestBase.php
+++ /dev/null
@@ -1,188 +0,0 @@
-<?php
-
-namespace Drupal\inline_entity_form\Tests;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Base Class for Inline Entity Form Tests.
- */
-abstract class InlineEntityFormTestBase extends WebTestBase {
-
-  /**
-   * User with permissions to create content.
-   *
-   * @var \Drupal\user\Entity\User
-   */
-  protected $user;
-
-  /**
-   * Node storage.
-   *
-   * @var \Drupal\Core\Entity\ContentEntityStorageInterface;
-   */
-  protected $nodeStorage;
-
-  /**
-   * Field config storage.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorage
-   */
-  protected $fieldStorageConfigStorage;
-
-  /**
-   * Field config storage.
-   *
-   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
-   */
-  protected $fieldConfigStorage;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->nodeStorage = $this->container->get('entity_type.manager')->getStorage('node');
-    $this->fieldStorageConfigStorage = $this->container->get('entity_type.manager')->getStorage('field_storage_config');
-    $this->fieldConfigStorage = $this->container->get('entity_type.manager')->getStorage('field_config');
-  }
-
-
-  /**
-   * Gets IEF button name.
-   *
-   * @param array $xpath
-   *   Xpath of the button.
-   *
-   * @return string
-   *   The name of the button.
-   */
-  protected function getButtonName($xpath) {
-    $retval = '';
-    /** @var \SimpleXMLElement[] $elements */
-    if ($elements = $this->xpath($xpath)) {
-      foreach ($elements[0]->attributes() as $name => $value) {
-        if ($name == 'name') {
-          $retval = $value;
-          break;
-        }
-      }
-    }
-    return $retval;
-  }
-
-  /**
-   * Passes if no node is found for the title.
-   *
-   * @param $title
-   *   Node title to check.
-   * @param $message
-   *   Message to display.
-   */
-  protected function assertNoNodeByTitle($title, $message = '') {
-    if (!$message) {
-      $message = "No node with title: $title";
-    }
-    $node = $this->getNodeByTitle($title);
-
-    $this->assertTrue(empty($node), $message);
-  }
-
-  /**
-   * Passes if node is found for the title.
-   *
-   * @param $title
-   *   Node title to check.
-   * @param $message
-   *   Message to display.
-   */
-  protected function assertNodeByTitle($title, $bundle = NULL, $message = '') {
-    if (!$message) {
-      $message = "Node with title found: $title";
-    }
-    $node = $this->getNodeByTitle($title);
-    if ($this->assertTrue(!empty($node), $message)) {
-      if ($bundle) {
-        $this->assertEqual($node->bundle(), $bundle, "Node is correct bundle: $bundle");
-      }
-    }
-  }
-
-  /**
-   * Ensures that an entity with a specific label exists.
-   *
-   * @param string $label
-   *   The label of the entity.
-   * @param string $entity_type_id
-   *   The entity type ID.
-   * @param string $bundle
-   *   (optional) The bundle this entity should have.
-   */
-  protected function assertEntityByLabel($label, $entity_type_id = 'node', $bundle = NULL) {
-    $entity_type_manager = \Drupal::entityTypeManager();
-    $entity_type = $entity_type_manager->getDefinition($entity_type_id);
-    $label_key = $entity_type->getKey('label');
-    $bundle_key = $entity_type->getKey('bundle');
-
-    $query = $entity_type_manager->getStorage($entity_type_id)->getQuery();
-    $query->condition($label_key, $label);
-
-    if ($bundle && $bundle_key) {
-      $query->condition($bundle_key, $bundle);
-    }
-
-    $result = $query->execute();
-    $this->assertTrue(!empty($result));
-  }
-
-  /**
-   * Checks for check correct fields on form displays based on exported config
-   * in inline_entity_form_test module.
-   *
-   * @param $form_display
-   *   The form display to check.
-   */
-  protected function checkFormDisplayFields($form_display, $prefix) {
-    $form_display_fields = [
-      'node.ief_test_custom.default' => [
-        'expected' => [
-          '[title][0][value]',
-          '[uid][0][target_id]',
-          '[created][0][value][date]',
-          '[created][0][value][time]',
-          '[promote][value]',
-          '[sticky][value]',
-          '[positive_int][0][value]',
-        ],
-        'unexpected' => [],
-      ],
-      'node.ief_test_custom.inline' => [
-        'expected' => [
-          '[title][0][value]',
-          '[positive_int][0][value]',
-        ],
-        'unexpected' => [
-          '[uid][0][target_id]',
-          '[created][0][value][date]',
-          '[created][0][value][time]',
-          '[promote][value]',
-          '[sticky][value]',
-        ],
-      ],
-    ];
-    if ($fields = $form_display_fields[$form_display]) {
-      $this->assert('debug', 'Checking form dispaly: ' . $form_display);
-      foreach ($fields['expected'] as $expected_field) {
-        $this->assertFieldByName($prefix . $expected_field);
-      }
-      foreach ($fields['unexpected'] as $unexpected_field) {
-        $this->assertNoFieldByName($prefix . $unexpected_field, NULL);
-      }
-    }
-    else {
-      // Test calling unexported form display if we are here.
-      throw new \Exception('Form display not found: ' . $form_display);
-    }
-  }
-
-}
diff --git a/web/modules/inline_entity_form/src/Tests/SimpleWidgetWebTest.php b/web/modules/inline_entity_form/src/Tests/SimpleWidgetWebTest.php
deleted file mode 100644
index 531c602129..0000000000
--- a/web/modules/inline_entity_form/src/Tests/SimpleWidgetWebTest.php
+++ /dev/null
@@ -1,248 +0,0 @@
-<?php
-
-namespace Drupal\inline_entity_form\Tests;
-
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\node\NodeInterface;
-
-/**
- * Tests the IEF simple widget.
- *
- * @group inline_entity_form
- */
-class SimpleWidgetWebTest extends InlineEntityFormTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['inline_entity_form_test'];
-
-  /**
-   * Prepares environment for
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->user = $this->createUser([
-      'create ief_simple_single content',
-      'create ief_test_custom content',
-      'edit any ief_simple_single content',
-      'edit own ief_test_custom content',
-      'view own unpublished content',
-      'create ief_simple_entity_no_bundle content',
-      'administer entity_test__without_bundle content',
-    ]);
-  }
-
-  /**
-   * Tests simple IEF widget with different cardinality options.
-   *
-   * @throws \Exception
-   */
-  protected function testSimpleCardinalityOptions() {
-    $this->drupalLogin($this->user);
-    $cardinality_options = [
-      1 => 1,
-      2 => 2,
-      FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => 3,
-    ];
-    /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
-    $field_storage = $this->fieldStorageConfigStorage->load('node.single');
-    foreach ($cardinality_options as $cardinality => $limit) {
-      $field_storage->setCardinality($cardinality);
-      $field_storage->save();
-
-      $this->drupalGet('node/add/ief_simple_single');
-
-      $this->assertText('Single node', 'Inline entity field widget title found.');
-      $this->assertText('Reference a single node.', 'Inline entity field description found.');
-
-      $add_more_xpath = '//input[@data-drupal-selector="edit-single-add-more"]';
-      if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
-        $this->assertFieldByXPath($add_more_xpath, NULL, 'Add more button exists');
-      }
-      else {
-        $this->assertNoFieldByXPath($add_more_xpath, NULL, 'Add more button does NOT exist');
-      }
-
-      $host_title = 'Host node cardinality: ' . $cardinality;
-      $edit = ['title[0][value]' => $host_title];
-      for ($item_number = 0; $item_number < $limit; $item_number++) {
-        $edit["single[$item_number][inline_entity_form][title][0][value]"] = 'Child node nr.' . $item_number;
-        if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
-          $next_item_number = $item_number + 1;
-          $this->assertNoFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does not appear before 'Add More' clicked");
-          if ($item_number < $limit - 1) {
-            $this->drupalPostAjaxForm(NULL, $edit, 'single_add_more');
-            $this->assertFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does  appear after 'Add More' clicked");
-            // Make sure only 1 item is added.
-            $unexpected_item_number = $next_item_number + 1;
-            $this->assertNoFieldByName("single[$unexpected_item_number][inline_entity_form][title][0][value]", NULL, "Extra Item $unexpected_item_number is not added after 'Add More' clicked");
-          }
-        }
-      }
-      $this->drupalPostForm(NULL, $edit, t('Save'));
-
-      for ($item_number = 0; $item_number < $limit; $item_number++) {
-        $this->assertText('Child node nr.' . $item_number, 'Label of referenced entity found.');
-      }
-
-      $host_node = $this->getNodeByTitle($host_title);
-      $this->checkEditAccess($host_node, $limit, $cardinality);
-    }
-  }
-
-  /**
-   * Test Validation on Simple Widget.
-   *
-   * @throws \Exception
-   */
-  protected function testSimpleValidation() {
-    $this->drupalLogin($this->user);
-    $host_node_title = 'Host Validation Node';
-    $this->drupalGet('node/add/ief_simple_single');
-
-    $this->assertText('Single node', 'Inline entity field widget title found.');
-    $this->assertText('Reference a single node.', 'Inline entity field description found.');
-    $this->assertText('Positive int', 'Positive int field found.');
-
-    $edit = ['title[0][value]' => $host_node_title];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-
-    $this->assertText('Title field is required.', 'Title validation fires on Inline Entity Form widget.');
-    $this->assertUrl('node/add/ief_simple_single', [], 'On add page after validation error.');
-
-    $child_title = 'Child node ' . $this->randomString();
-    $edit['single[0][inline_entity_form][title][0][value]'] = $child_title;
-    $edit['single[0][inline_entity_form][positive_int][0][value]'] = -1;
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertNoText('Title field is required.', 'Title validation passes on Inline Entity Form widget.');
-    $this->assertText('Positive int must be higher than or equal to 1', 'Field validation fires on Inline Entity Form widget.');
-    $this->assertUrl('node/add/ief_simple_single', [], 'On add page after validation error.');
-
-    $edit['single[0][inline_entity_form][positive_int][0][value]'] = 1;
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertNoText('Title field is required.', 'Title validation passes on Inline Entity Form widget.');
-    $this->assertNoText('Positive int must be higher than or equal to 1', 'Field validation fires on Inline Entity Form widget.');
-
-    // Check that nodes were created correctly.
-    $host_node = $this->getNodeByTitle($host_node_title);
-    if ($this->assertNotNull($host_node, 'Host node created.')) {
-      $this->assertUrl('node/' . $host_node->id(), [], 'On node view page after node add.');
-      $child_node = $this->getNodeByTitle($child_title);
-      if ($this->assertNotNull($child_node)) {
-        $this->assertEqual($host_node->single[0]->target_id, $child_node->id(), 'Child node is referenced');
-        $this->assertEqual($child_node->positive_int[0]->value, 1, 'Child node int field correct.');
-        $this->assertEqual($child_node->bundle(), 'ief_test_custom', 'Child node is correct bundle.');
-      }
-    }
-  }
-
-  /**
-   * Tests if the entity create access works in simple widget.
-   */
-  public function testSimpleCreateAccess() {
-    // Create a user who does not have access to create ief_test_custom nodes.
-    $this->user = $this->createUser([
-      'create ief_simple_single content',
-    ]);
-    $this->drupalLogin($this->user);
-    $this->drupalGet('node/add/ief_simple_single');
-    $this->assertNoFieldByName('single[0][inline_entity_form][title][0][value]', NULL);
-  }
-
-  /**
-   * Tests that user only has access to the their own nodes.
-   *
-   * @param \Drupal\node\Entity\Node $host_node
-   *   The node of the type of ief_simple_single
-   * @param int $child_count
-   *   The number of entity reference values in the "single" field.
-   */
-  protected function checkEditAccess(NodeInterface $host_node, $child_count, $cardinality) {
-    $other_user = $this->createUser([
-      'edit own ief_test_custom content',
-      'edit any ief_simple_single content',
-    ]);
-    /** @var  \Drupal\node\Entity\Node $first_child_node */
-    $first_child_node = $host_node->single[0]->entity;
-    $first_child_node->setOwner($other_user);
-    $first_child_node->save();
-    $this->drupalGet("node/{$host_node->id()}/edit");
-    $this->assertText($first_child_node->label());
-    $this->assertNoFieldByName('single[0][inline_entity_form][title][0][value]', NULL, 'Form of child node with no edit access is not found.');
-    // Check that the forms for other child nodes(if any) appear on the form.
-    $delta = 1;
-    while ($delta < $child_count) {
-      /** @var \Drupal\node\Entity\Node $child_node */
-      $child_node = $host_node->single[$delta]->entity;
-      $this->assertFieldByName("single[$delta][inline_entity_form][title][0][value]", $child_node->label(), 'Form of child node with edit access is found.');
-      $delta++;
-    }
-    // Check that there is NOT an extra "add" form when editing.
-    $unexpected_item_number = $child_count;
-    $this->assertNoFieldByName("single[$unexpected_item_number][inline_entity_form][title][0][value]", NULL, 'No empty "add" entity form is found on edit.');
-    if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
-      $next_item_number = $child_count;
-      $this->drupalPostAjaxForm(NULL, [], 'single_add_more');
-      $this->assertFieldByName("single[$next_item_number][inline_entity_form][title][0][value]", NULL, "Item $next_item_number does appear after 'Add More' clicked");
-      // Make sure only 1 item is added.
-      $unexpected_item_number = $next_item_number + 1;
-      $this->assertNoFieldByName("single[$unexpected_item_number][inline_entity_form][title][0][value]", NULL, "Extra Item $unexpected_item_number is not added after 'Add More' clicked");
-    }
-
-    // Now that we have confirmed the correct fields appear, lets update the
-    // values and save them. We do not have access to form for delta 0 because
-    // it is owned by another user.
-    $delta = 1;
-    $new_titles = [];
-    $edit = [];
-    // Loop through an update all child node titles.
-    while ($delta < $child_count) {
-      /** @var \Drupal\node\Entity\Node $child_node */
-      $child_node = $host_node->single[$delta]->entity;
-      $new_titles[$delta] = $child_node->label() . ' - updated';
-      $edit["single[$delta][inline_entity_form][title][0][value]"] = $new_titles[$delta];
-      $delta++;
-    }
-    // If CARDINALITY_UNLIMITED then we should have 1 extra form open.
-    if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
-      $new_titles[$delta] = 'Title for new child';
-      $edit["single[$delta][inline_entity_form][title][0][value]"] = $new_titles[$delta];
-    }
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertText("IEF single simple {$host_node->label()} has been updated.");
-
-    // Reset cache for nodes.
-    $node_ids = [$host_node->id()];
-    foreach ($host_node->single as $item) {
-      $node_ids[] = $item->entity->id();
-    }
-    $this->nodeStorage->resetCache($node_ids);
-    $host_node = $this->nodeStorage->load($host_node->id());
-    // Check that titles were updated.
-    foreach ($new_titles as $delta => $new_title) {
-      $child_node = $host_node->single[$delta]->entity;
-      $this->assertEqual($child_node->label(), $new_title, "Child $delta node title updated");
-    }
-  }
-
-  /**
-   * Ensures that an entity without bundles can be used with the simple widget.
-   */
-  public function testEntityWithoutBundle() {
-    $this->drupalLogin($this->user);
-
-    $edit = [
-      'title[0][value]' => 'Node title',
-      'field_ief_entity_no_bundle[0][inline_entity_form][name][0][value]' => 'Entity title',
-    ];
-    $this->drupalPostForm('node/add/ief_simple_entity_no_bundle', $edit, 'Save');
-
-    $this->assertNodeByTitle('Node title', 'ief_simple_entity_no_bundle');
-    $this->assertEntityByLabel('Entity title', 'entity_test__without_bundle');
-  }
-
-}
diff --git a/web/modules/inline_entity_form/src/Tests/TranslationTest.php b/web/modules/inline_entity_form/src/Tests/TranslationTest.php
deleted file mode 100644
index b58949702b..0000000000
--- a/web/modules/inline_entity_form/src/Tests/TranslationTest.php
+++ /dev/null
@@ -1,173 +0,0 @@
-<?php
-
-namespace Drupal\inline_entity_form\Tests;
-
-use Drupal\node\Entity\Node;
-
-/**
- * Tests translating inline entities.
- *
- * @group inline_entity_form
- */
-class TranslationTest extends InlineEntityFormTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = [
-    'content_translation', 'inline_entity_form_test', 'language',
-  ];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->user = $this->createUser([
-      'create ief_reference_type content',
-      'edit any ief_reference_type content',
-      'delete any ief_reference_type content',
-      'create ief_test_complex content',
-      'edit any ief_test_complex content',
-      'delete any ief_test_complex content',
-      'view own unpublished content',
-      'administer content translation',
-      'translate any entity',
-      'create content translations',
-      'administer languages',
-    ]);
-    $this->drupalLogin($this->user);
-
-    // Enable translations for both entity types.
-    $edit = [
-      'entity_types[node]' => TRUE,
-    ];
-    foreach (['ief_test_complex', 'ief_reference_type'] as $node_type) {
-      $edit['settings[node][' . $node_type . '][translatable]'] = TRUE;
-      $edit['settings[node][' . $node_type . '][settings][language][language_alterable]'] = TRUE;
-    }
-    $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
-
-    // Allow referencing existing entities.
-    $form_display_storage = $this->container->get('entity_type.manager')->getStorage('entity_form_display');
-    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */
-    $display = $form_display_storage->load('node.ief_test_complex.default');
-    $component = $display->getComponent('multi');
-    $component['settings']['allow_existing'] = TRUE;
-    $display->setComponent('multi', $component)->save();
-  }
-
-  /**
-   * Tests translating inline entities.
-   */
-  protected function testTranslation() {
-    // Create a German node with a French translation.
-    $first_inline_node = Node::create([
-      'type' => 'ief_reference_type',
-      'langcode' => 'de',
-      'title' => 'An inline node',
-      'first_name' => 'Dieter',
-    ]);
-    $translation = $first_inline_node->toArray();
-    $translation['title'][0]['value'] = 'An inline node in French';
-    $translation['first_name'][0]['value'] = 'Pierre';
-    $first_inline_node->addTranslation('fr', $translation);
-    $first_inline_node->save();
-
-    $this->drupalGet('node/add/ief_test_complex');
-    // Reference the German node.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add existing node" and @data-drupal-selector="edit-multi-actions-ief-add-existing"]'));
-    $edit = [
-      'multi[form][entity_id]' => 'An inline node (' . $first_inline_node->id() . ')',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @data-drupal-selector="edit-multi-form-actions-ief-reference-save"]'));
-    $this->assertResponse(200, 'Adding a new referenced entity was successful.');
-
-    // Add a new English inline node.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Add new node" and @data-drupal-selector="edit-multi-actions-ief-add"]'));
-    $edit = [
-      'multi[form][inline_entity_form][title][0][value]' => 'Another inline node',
-      'multi[form][inline_entity_form][first_name][0][value]' => 'John',
-      'multi[form][inline_entity_form][last_name][0][value]' => 'Smith',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Create node" and @data-drupal-selector="edit-multi-form-inline-entity-form-actions-ief-add-save"]'));
-    $this->assertResponse(200, 'Creating a new inline entity was successful.');
-
-    $edit = [
-      'title[0][value]' => 'A node',
-      'langcode[0][value]' => 'en',
-    ];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertResponse(200, 'Saving the parent entity was successful.');
-
-    // Both inline nodes should now be in English.
-    $first_inline_node = $this->drupalGetNodeByTitle('An inline node');
-    $second_inline_node = $this->drupalGetNodeByTitle('Another inline node');
-    $this->assertEqual($first_inline_node->get('langcode')->value, 'en', 'The first inline entity has the correct langcode.');
-    $this->assertEqual($second_inline_node->get('langcode')->value, 'en', 'The second inline entity has the correct langcode.');
-
-    // Edit the node, change the source language to German.
-    $node = $this->drupalGetNodeByTitle('A node');
-    $this->drupalGet('node/' . $node->id() . '/edit');
-    $edit = [
-      'langcode[0][value]' => 'de',
-    ];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertResponse(200, 'Saving the parent entity was successful.');
-
-    // Both inline nodes should now be in German.
-    $first_inline_node = $this->drupalGetNodeByTitle('An inline node', TRUE);
-    $second_inline_node = $this->drupalGetNodeByTitle('Another inline node', TRUE);
-    $this->assertEqual($first_inline_node->get('langcode')->value, 'de', 'The first inline entity has the correct langcode.');
-    $this->assertEqual($second_inline_node->get('langcode')->value, 'de', 'The second inline entity has the correct langcode.');
-
-    // Add a German -> French translation.
-    $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr');
-
-    // Confirm that the translatability clue has been removed.
-    $widget_title_element = $this->xpath('//fieldset[@id="edit-multi"]/legend/span');
-    $this->assertEqual((string) $widget_title_element[0], 'Multiple nodes', 'The widget has the expected title.');
-    // Confirm that the add and remove buttons are not present.
-    $this->assertFalse((bool) $this->xpath('//input[@type="submit" and @value="Add new node" and @data-drupal-selector="edit-multi-actions-ief-add"]'), 'Add new node button does not appear in the table.');
-    $this->assertFalse((bool) $this->xpath('//input[@type="submit" and @value="Remove"]'), 'Remove button does not appear in the table.');
-    // Confirm the presence of the two node titles, in the expected languages.
-    $this->assertTrue((bool) $this->xpath('//td[@class="inline-entity-form-node-label" and contains(.,"An inline node in French")]'), 'First inline node title appears in the table');
-    $this->assertTrue((bool) $this->xpath('//td[@class="inline-entity-form-node-label" and contains(.,"Another inline node")]'), 'Second node title appears in the table');
-
-    // Edit the translations of both inline entities.
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Edit" and @data-drupal-selector="edit-multi-entities-0-actions-ief-entity-edit"]'));
-    $this->assertNoText('Last name', 'The non-translatable last_name field is hidden.');
-    $edit = [
-      'multi[form][inline_entity_form][entities][0][form][title][0][value]' => 'An inline node in French!',
-      'multi[form][inline_entity_form][entities][0][form][first_name][0][value]' => 'Damien',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Update node" and @data-drupal-selector="edit-multi-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]'));
-
-    $this->drupalPostAjaxForm(NULL, [], $this->getButtonName('//input[@type="submit" and @value="Edit" and @data-drupal-selector="edit-multi-entities-1-actions-ief-entity-edit"]'));
-    $edit = [
-      'multi[form][inline_entity_form][entities][1][form][title][0][value]' => 'Another inline node in French!',
-      'multi[form][inline_entity_form][entities][1][form][first_name][0][value]' => 'Jacques',
-    ];
-    $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Update node" and @data-drupal-selector="edit-multi-form-inline-entity-form-entities-1-form-actions-ief-edit-save"]'));
-
-    $this->drupalPostForm(NULL, [], t('Save (this translation)'));
-    $this->assertResponse(200, 'Saving the parent entity was successful.');
-
-    // Load using the original titles, confirming they haven't changed.
-    $first_inline_node = $this->drupalGetNodeByTitle('An inline node', TRUE);
-    $second_inline_node = $this->drupalGetNodeByTitle('Another inline node', TRUE);
-    // Confirm that the expected translated values are present.
-    $this->assertTrue($first_inline_node->hasTranslation('fr'), 'The first inline entity has a FR translation');
-    $this->assertTrue($second_inline_node->hasTranslation('fr'), 'The second inline entity has a FR translation');
-    $first_translation = $first_inline_node->getTranslation('fr');
-    $this->assertEqual($first_translation->title->value, 'An inline node in French!');
-    $this->assertEqual($first_translation->first_name->value, 'Damien');
-    $second_translation = $second_inline_node->getTranslation('fr');
-    $this->assertEqual($second_translation->title->value, 'Another inline node in French!');
-    $this->assertEqual($second_translation->first_name->value, 'Jacques');
-  }
-
-}
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_complex_simple.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_complex_simple.default.yml
index a82aa29724..e81fe9a830 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_complex_simple.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_complex_simple.default.yml
@@ -57,6 +57,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_reference_type.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_reference_type.default.yml
index 90883dfd34..646b6e37e2 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_reference_type.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_reference_type.default.yml
@@ -51,6 +51,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_entity_no_bundle.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_entity_no_bundle.default.yml
index a320b9430b..ed578fe369 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_entity_no_bundle.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_entity_no_bundle.default.yml
@@ -50,8 +50,8 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
 hidden: {  }
-
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml
index 3ac6ae71f7..634199ed68 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_simple_single.default.yml
@@ -37,6 +37,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_complex.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_complex.default.yml
index 0e4cbf68c7..746d7f8c90 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_complex.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_complex.default.yml
@@ -37,6 +37,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml
index 07d71a96f5..8ba9401755 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_custom.default.yml
@@ -44,6 +44,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested1.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested1.default.yml
index 6abd3d8875..9ca5c25748 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested1.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested1.default.yml
@@ -37,6 +37,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested2.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested2.default.yml
index d97bd49e05..f50c43385c 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested2.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested2.default.yml
@@ -37,6 +37,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested3.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested3.default.yml
index 8394cc3506..3700da6d3f 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested3.default.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/core.entity_form_display.node.ief_test_nested3.default.yml
@@ -37,6 +37,7 @@ content:
     weight: 5
     settings:
       match_operator: CONTAINS
+      match_limit: 10
       size: 60
       placeholder: ''
     third_party_settings: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_entity_no_bundle.field_ief_entity_no_bundle.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_entity_no_bundle.field_ief_entity_no_bundle.yml
index be73463eb5..f0e0cee7af 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_entity_no_bundle.field_ief_entity_no_bundle.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.field.node.ief_simple_entity_no_bundle.field_ief_entity_no_bundle.yml
@@ -23,4 +23,3 @@ settings:
       field: _none
     auto_create: false
 field_type: entity_reference
-
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.storage.node.field_ief_entity_no_bundle.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.storage.node.field_ief_entity_no_bundle.yml
index 9b21f692ac..105911519f 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.storage.node.field_ief_entity_no_bundle.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/field.storage.node.field_ief_entity_no_bundle.yml
@@ -18,4 +18,3 @@ translatable: true
 indexes: {  }
 persist_with_no_fields: false
 custom_storage: false
-
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_entity_no_bundle.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_entity_no_bundle.yml
index dfd0b7bde1..c1220552a5 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_entity_no_bundle.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/install/node.type.ief_simple_entity_no_bundle.yml
@@ -8,4 +8,3 @@ help: ''
 new_revision: true
 preview_mode: 1
 display_submitted: true
-
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml
new file mode 100644
index 0000000000..4ddf2dfdd0
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml
@@ -0,0 +1,21 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_1
+id: node.err_level_1.promote
+field_name: promote
+entity_type: node
+bundle: err_level_1
+label: 'Promoted to front page'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: 'On'
+  off_label: 'Off'
+field_type: boolean
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml
new file mode 100644
index 0000000000..cb90dffd2f
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml
@@ -0,0 +1,21 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_2
+id: node.err_level_2.promote
+field_name: promote
+entity_type: node
+bundle: err_level_2
+label: 'Promoted to front page'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: 'On'
+  off_label: 'Off'
+field_type: boolean
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml
new file mode 100644
index 0000000000..39c23b6b8c
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml
@@ -0,0 +1,21 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_3
+id: node.err_level_3.promote
+field_name: promote
+entity_type: node
+bundle: err_level_3
+label: 'Promoted to front page'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: 'On'
+  off_label: 'Off'
+field_type: boolean
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml
new file mode 100644
index 0000000000..322840859d
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml
@@ -0,0 +1,62 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_1.field_level_2_entity_no_bundle
+    - field.field.node.err_level_1.field_level_2_items
+    - node.type.err_level_1
+  module:
+    - inline_entity_form
+id: node.err_level_1.default
+targetEntityType: node
+bundle: err_level_1
+mode: default
+content:
+  field_level_2_entity_no_bundle:
+    weight: 32
+    settings:
+      form_mode: compact
+      revision: true
+      label_singular: ''
+      label_plural: ''
+      allow_new: true
+      match_operator: CONTAINS
+      override_labels: false
+      collapsible: false
+      collapsed: false
+      allow_existing: false
+      allow_duplicate: false
+    third_party_settings: {  }
+    type: inline_entity_form_complex
+    region: content
+  field_level_2_items:
+    weight: 31
+    settings:
+      match_operator: CONTAINS
+      form_mode: default
+      override_labels: false
+      label_singular: ''
+      label_plural: ''
+      allow_new: true
+      allow_existing: false
+      revision: true
+      collapsible: false
+      collapsed: false
+      allow_duplicate: false
+    third_party_settings: {  }
+    type: inline_entity_form_complex
+    region: content
+  title:
+    type: string_textfield
+    weight: -5
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+    region: content
+hidden:
+  created: true
+  path: true
+  promote: true
+  sticky: true
+  uid: true
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml
new file mode 100644
index 0000000000..849b2b4030
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml
@@ -0,0 +1,38 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_2.field_level_3_items
+    - node.type.err_level_2
+  module:
+    - inline_entity_form
+id: node.err_level_2.default
+targetEntityType: node
+bundle: err_level_2
+mode: default
+content:
+  field_level_3_items:
+    weight: 1
+    settings:
+      match_operator: CONTAINS
+      form_mode: default
+      override_labels: false
+      label_singular: ''
+      label_plural: ''
+      allow_new: true
+      allow_existing: false
+    third_party_settings: {  }
+    type: inline_entity_form_complex
+  title:
+    type: string_textfield
+    weight: 0
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+hidden:
+  created: true
+  path: true
+  promote: true
+  sticky: true
+  uid: true
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml
new file mode 100644
index 0000000000..7d94d96b48
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml
@@ -0,0 +1,23 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_3
+id: node.err_level_3.default
+targetEntityType: node
+bundle: err_level_3
+mode: default
+content:
+  title:
+    type: string_textfield
+    weight: -5
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+hidden:
+  created: true
+  path: true
+  promote: true
+  sticky: true
+  uid: true
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml
new file mode 100644
index 0000000000..b3de56d890
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml
@@ -0,0 +1,34 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_1.field_level_2_items
+    - node.type.err_level_1
+  module:
+    - entity_reference_revisions
+    - user
+id: node.err_level_1.default
+targetEntityType: node
+bundle: err_level_1
+mode: default
+content:
+  field_level_2_entity_no_bundle:
+    weight: 102
+    label: above
+    settings:
+      view_mode: default
+      link: ''
+    third_party_settings: {  }
+    type: entity_reference_revisions_entity_view
+    region: content
+  field_level_2_items:
+    weight: 101
+    label: above
+    settings:
+      view_mode: default
+      link: ''
+    third_party_settings: {  }
+    type: entity_reference_revisions_entity_view
+  links:
+    weight: 100
+hidden: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml
new file mode 100644
index 0000000000..ea334e8d86
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml
@@ -0,0 +1,16 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - node.type.err_level_1
+  module:
+    - user
+id: node.err_level_1.teaser
+targetEntityType: node
+bundle: err_level_1
+mode: teaser
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml
new file mode 100644
index 0000000000..7a2e001c84
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml
@@ -0,0 +1,25 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_2.field_level_3_items
+    - node.type.err_level_2
+  module:
+    - entity_reference_revisions
+    - user
+id: node.err_level_2.default
+targetEntityType: node
+bundle: err_level_2
+mode: default
+content:
+  field_level_3_items:
+    weight: 101
+    label: above
+    settings:
+      view_mode: default
+      link: ''
+    third_party_settings: {  }
+    type: entity_reference_revisions_entity_view
+  links:
+    weight: 100
+hidden: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml
new file mode 100644
index 0000000000..8ccdf1503c
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml
@@ -0,0 +1,16 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - node.type.err_level_2
+  module:
+    - user
+id: node.err_level_2.teaser
+targetEntityType: node
+bundle: err_level_2
+mode: teaser
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml
new file mode 100644
index 0000000000..d3de6a5dce
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml
@@ -0,0 +1,15 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_3
+  module:
+    - user
+id: node.err_level_3.default
+targetEntityType: node
+bundle: err_level_3
+mode: default
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml
new file mode 100644
index 0000000000..c119fd326a
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml
@@ -0,0 +1,16 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - node.type.err_level_3
+  module:
+    - user
+id: node.err_level_3.teaser
+targetEntityType: node
+bundle: err_level_3
+mode: teaser
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml
new file mode 100644
index 0000000000..5906fffca3
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml
@@ -0,0 +1,27 @@
+uuid: 616ca481-7579-4873-aee6-6aaf74375d7b
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_level_2_entity_no_bundle
+    - node.type.err_level_1
+  module:
+    - entity_reference_revisions
+id: node.err_level_1.field_level_2_entity_no_bundle
+field_name: field_level_2_entity_no_bundle
+entity_type: node
+bundle: err_level_1
+label: 'Test entity no bundle'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:entity_test_no_bundle'
+  handler_settings:
+    target_bundles: null
+    sort:
+      field: _none
+    auto_create: false
+field_type: entity_reference_revisions
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml
new file mode 100644
index 0000000000..025d09ce17
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml
@@ -0,0 +1,29 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_level_2_items
+    - node.type.err_level_1
+    - node.type.err_level_2
+  module:
+    - entity_reference_revisions
+id: node.err_level_1.field_level_2_items
+field_name: field_level_2_items
+entity_type: node
+bundle: err_level_1
+label: 'Level 2 Items'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:node'
+  handler_settings:
+    target_bundles:
+      err_level_2: err_level_2
+    sort:
+      field: _none
+    auto_create: false
+    auto_create_bundle: ''
+field_type: entity_reference_revisions
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml
new file mode 100644
index 0000000000..e285cec7b3
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml
@@ -0,0 +1,29 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_level_3_items
+    - node.type.err_level_2
+    - node.type.err_level_3
+  module:
+    - entity_reference_revisions
+id: node.err_level_2.field_level_3_items
+field_name: field_level_3_items
+entity_type: node
+bundle: err_level_2
+label: 'Level 3 Items'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:node'
+  handler_settings:
+    target_bundles:
+      err_level_3: err_level_3
+    sort:
+      field: _none
+    auto_create: false
+    auto_create_bundle: ''
+field_type: entity_reference_revisions
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml
new file mode 100644
index 0000000000..bb09a02cb3
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml
@@ -0,0 +1,21 @@
+uuid: 2111cc32-c893-4518-864a-74aed74266c7
+langcode: en
+status: true
+dependencies:
+  module:
+    - entity_reference_revisions
+    - entity_test
+    - node
+id: node.field_level_2_entity_no_bundle
+field_name: field_level_2_entity_no_bundle
+entity_type: node
+type: entity_reference_revisions
+settings:
+  target_type: entity_test_no_bundle
+module: entity_reference_revisions
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml
new file mode 100644
index 0000000000..1070cc3fc1
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml
@@ -0,0 +1,19 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  module:
+    - entity_reference_revisions
+    - node
+id: node.field_level_2_items
+field_name: field_level_2_items
+entity_type: node
+type: entity_reference_revisions
+settings:
+  target_type: node
+module: entity_reference_revisions
+locked: false
+cardinality: -1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml
new file mode 100644
index 0000000000..757c48a72a
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml
@@ -0,0 +1,19 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  module:
+    - entity_reference_revisions
+    - node
+id: node.field_level_3_items
+field_name: field_level_3_items
+entity_type: node
+type: entity_reference_revisions
+settings:
+  target_type: node
+module: entity_reference_revisions
+locked: false
+cardinality: -1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml
new file mode 100644
index 0000000000..4865eb9e31
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml
@@ -0,0 +1,9 @@
+trimIefIdParentslangcode: en
+status: true
+name: 'Entity Reference Revisions (Level 1)'
+type: err_level_1
+description: 'Top level content type with an entity_reference_revisions field type to another content type.'
+help: ''
+new_revision: true
+preview_mode: 1
+display_submitted: false
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml
new file mode 100644
index 0000000000..289dc9dc81
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml
@@ -0,0 +1,9 @@
+trimIefIdParentslangcode: en
+status: true
+name: 'Entity Reference Revisions (Level 2)'
+type: err_level_2
+description: 'Second level content type with an entity_reference_revisions field type to another content type.'
+help: ''
+new_revision: true
+preview_mode: 1
+display_submitted: false
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml
new file mode 100644
index 0000000000..b22f916962
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml
@@ -0,0 +1,9 @@
+trimIefIdParentslangcode: en
+status: true
+name: 'Entity Reference Revisions (Level 3)'
+type: err_level_3
+description: 'Third level content type.'
+help: ''
+new_revision: true
+preview_mode: 1
+display_submitted: false
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml
index 699134915f..254568bd5a 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/inline_entity_form_test.info.yml
@@ -1,17 +1,15 @@
 name: 'IEF test'
 type: module
 description: 'Support module for the Inline entity form module tests.'
-# core: 8.x
+core_version_requirement: ^8.7.7 || ^9
 package: Testing
-# version: VERSION
 dependencies:
-  - inline_entity_form
-  - node
-  - file
-  - image
+  - inline_entity_form:inline_entity_form
+  - drupal:node
+  - drupal:file
+  - drupal:image
 
-# Information added by Drupal.org packaging script on 2018-05-22
-version: '8.x-1.0-rc1'
-core: '8.x'
+# Information added by Drupal.org packaging script on 2020-05-12
+version: '8.x-1.0-rc6'
 project: 'inline_entity_form'
-datestamp: 1527030788
+datestamp: 1589280849
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/src/IefTest.php b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/src/IefTest.php
index 344ee7c587..dc27f81100 100644
--- a/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/src/IefTest.php
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_test/src/IefTest.php
@@ -45,7 +45,8 @@ public function buildForm(array $form, FormStateInterface $form_state, $form_mod
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
     $entity = $form['inline_entity_form']['#entity'];
-    drupal_set_message(t('Created @entity_type @label.', ['@entity_type' => $entity->getEntityType()->getLabel(), '@label' => $entity->label()]));
+    $message = $this->t('Created @entity_type @label.', ['@entity_type' => $entity->getEntityType()->getLabel(), '@label' => $entity->label()]);
+    $this->messenger()->addMessage($message);
   }
 
 }
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_reference_type.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_reference_type.yml
new file mode 100644
index 0000000000..27108ddd19
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_reference_type.yml
@@ -0,0 +1,17 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - node.type.ief_reference_type
+  module:
+    - content_translation
+third_party_settings:
+  content_translation:
+    enabled: true
+    bundle_settings:
+      untranslatable_fields_hide: '0'
+id: node.ief_reference_type
+target_entity_type_id: node
+target_bundle: ief_reference_type
+default_langcode: site_default
+language_alterable: true
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_test_complex.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_test_complex.yml
new file mode 100644
index 0000000000..7790a43430
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/config/install/language.content_settings.node.ief_test_complex.yml
@@ -0,0 +1,17 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - node.type.ief_test_complex
+  module:
+    - content_translation
+third_party_settings:
+  content_translation:
+    enabled: true
+    bundle_settings:
+      untranslatable_fields_hide: '0'
+id: node.ief_test_complex
+target_entity_type_id: node
+target_bundle: ief_test_complex
+default_langcode: site_default
+language_alterable: true
diff --git a/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/inline_entity_form_translation_test.info.yml b/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/inline_entity_form_translation_test.info.yml
new file mode 100644
index 0000000000..8f46dfe35d
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/modules/inline_entity_form_translation_test/inline_entity_form_translation_test.info.yml
@@ -0,0 +1,14 @@
+name: 'IEF translation test'
+type: module
+description: 'Support module for the Inline entity form module tests.'
+core_version_requirement: ^8.7.7 || ^9
+package: Testing
+dependencies:
+  - inline_entity_form_test:inline_entity_form_test
+  - drupal:language
+  - drupal:content_translation
+
+# Information added by Drupal.org packaging script on 2020-05-12
+version: '8.x-1.0-rc6'
+project: 'inline_entity_form'
+datestamp: 1589280849
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexSimpleWidgetTest.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexSimpleWidgetTest.php
new file mode 100644
index 0000000000..2a53a7dea2
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexSimpleWidgetTest.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+
+/**
+ * IEF complex field widget containing an IEF simple field widget tests.
+ *
+ * @group inline_entity_form
+ */
+class ComplexSimpleWidgetTest extends InlineEntityFormTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'inline_entity_form_test',
+    'field',
+    'field_ui',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'create ief_complex_simple content',
+      'create ief_simple_single content',
+      'create ief_test_custom content',
+      'view own unpublished content',
+    ]);
+    $this->drupalLogin($this->user);
+    $this->fieldConfigStorage = $this->container
+      ->get('entity_type.manager')
+      ->getStorage('field_config');
+  }
+
+  /**
+   * Test a Simple IEF widget inside of Complex IEF widget.
+   */
+  public function testSimpleInComplex() {
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $outer_required_options = [
+      TRUE,
+      FALSE,
+    ];
+    $cardinality_options = [
+      1 => 1,
+      2 => 2,
+      FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => 3,
+    ];
+    $first_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $outer_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $inner_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+    /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
+    $field_storage = $this->fieldStorageConfigStorage->load('node.ief_complex_outer');
+    /** @var \Drupal\Core\Field\FieldConfigInterface $field_config */
+    $field_config = $this->fieldConfigStorage->load('node.ief_complex_simple.ief_complex_outer');
+    foreach ($outer_required_options as $outer_required_option) {
+      $field_config->setRequired($outer_required_option);
+      $field_config->save();
+      foreach ($cardinality_options as $cardinality => $limit) {
+        $field_storage->setCardinality($cardinality);
+        $field_storage->save();
+
+        $this->drupalGet('node/add/ief_complex_simple');
+        if (!$outer_required_option) {
+          $assert_session->pageTextContains('Complex Outer');
+          // Field should not be available before ajax submit.
+          $assert_session->elementNotExists('xpath', $outer_title_field_xpath);
+          $assert_session
+            ->elementExists('xpath', '//input[@type="submit" and @value="Add new node"]')
+            ->press();
+          $this->assertNotEmpty($assert_session->waitForElement('xpath', $outer_title_field_xpath));
+        }
+        $outer_title = $this->randomMachineName(8);
+        $inner_title = $this->randomMachineName(8);
+        $assert_session->elementExists('xpath', $outer_title_field_xpath)->setValue($outer_title);
+        // Simple widget is required so should always show up. No need for
+        // add submit.
+        $assert_session->elementExists('xpath', $inner_title_field_xpath)->setValue($inner_title);
+        $create_outer_button_selector = '//input[@type="submit" and @value="Create node"]';
+        $assert_session->elementExists('xpath', $create_outer_button_selector)->press();
+        // After Ajax submit the ief title fields should be gone.
+        $this->assertNotEmpty($assert_session->waitForButton('Edit'));
+        $assert_session->elementNotExists('xpath', $outer_title_field_xpath);
+        $assert_session->elementNotExists('xpath', $inner_title_field_xpath);
+        $assert_session->elementNotExists('xpath', $create_outer_button_selector);
+
+        // The nodes should not actually be saved at this point.
+        $this->assertNoNodeByTitle($outer_title, 'Outer node was not created when widget submitted.');
+        $this->assertNoNodeByTitle($inner_title, 'Inner node was not created when widget submitted.');
+
+        $host_title = $this->randomMachineName(8);
+        $assert_session->elementExists('xpath', $first_title_field_xpath)->setValue($host_title);
+        $page->pressButton('Save');
+        $assert_session->pageTextContains("$host_title has been created.");
+        $assert_session->pageTextContains($outer_title);
+
+        // Check the nodes were created correctly.
+        $host_node = $this->drupalGetNodeByTitle($host_title);
+        $this->assertNotNull($host_node->ief_complex_outer->entity, 'Outer node was created.');
+        if (isset($host_node->ief_complex_outer->entity)) {
+          $outer_node = $host_node->ief_complex_outer->entity;
+          $this->assertEquals($outer_title, $outer_node->label(), "Outer node's title looks correct.");
+          $this->assertEquals('ief_simple_single', $outer_node->bundle(), "Outer node's type looks correct.");
+          $this->assertNotNull($outer_node->single->entity, 'Inner node was created');
+          if (isset($outer_node->single->entity)) {
+            $inner_node = $outer_node->single->entity;
+            $this->assertEquals($inner_title, $inner_node->label(), "Inner node's title looks correct.");
+            $this->assertEquals('ief_test_custom', $inner_node->bundle(), "Inner node's type looks correct.");
+          }
+        }
+      }
+    }
+  }
+
+}
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php
new file mode 100644
index 0000000000..9796ba450f
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php
@@ -0,0 +1,263 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+/**
+ * IEF complex entity reference revisions tests.
+ *
+ * @group inline_entity_form
+ */
+class ComplexWidgetRevisionsTest extends InlineEntityFormTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'field',
+    'field_ui',
+    'entity_test',
+    'entity_reference_revisions',
+    'inline_entity_form_test',
+  ];
+
+  /**
+   * URL to add new content.
+   *
+   * @var string
+   */
+  protected $formContentAddUrl;
+
+  /**
+   * Prepares environment for testing.
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'administer entity_test__without_bundle content',
+      'administer entity_test content',
+      'administer content types',
+      'create err_level_1 content',
+      'edit any err_level_1 content',
+      'delete any err_level_1 content',
+      'create err_level_2 content',
+      'edit any err_level_2 content',
+      'delete any err_level_2 content',
+      'create err_level_3 content',
+      'edit any err_level_3 content',
+      'delete any err_level_3 content',
+      'view own unpublished content',
+    ]);
+    $this->drupalLogin($this->user);
+
+    $this->formContentAddUrl = 'node/add/err_level_1';
+  }
+
+  /**
+   * Tests saving entity reference revisions' field types at depth.
+   */
+  public function testRevisionsAtDepth() {
+    // Get the xpath selectors for the input fields in this test.
+    $top_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $double_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+
+    // Get the xpath selectors for the buttons in this test.
+    $first_add_new_node_button_xpath = $this->getXpathForButtonWithValue('Add new node', 1);
+    $first_create_node_button_xpath = $this->getXpathForButtonWithValue('Create node', 1);
+    $first_edit_button_xpath = $this->getXpathForButtonWithValue('Edit', 1);
+    $first_update_button_xpath = $this->getXpathForButtonWithValue('Update node', 1);
+
+    $this->drupalGet($this->formContentAddUrl);
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    // Open up level 2 and 3 IEF forms.
+    $assert_session->elementExists('xpath', $first_add_new_node_button_xpath)->press();
+    $this->waitForElementRemoved('xpath', $first_add_new_node_button_xpath);
+    $assert_session->elementExists('xpath', $first_add_new_node_button_xpath)->press();
+
+    // Fill in and save level 3 IEF form.
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $double_nested_title_field_xpath));
+    $assert_session->elementExists('xpath', $double_nested_title_field_xpath)->setValue('Level 3');
+    $assert_session->elementExists('xpath', $first_create_node_button_xpath)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_edit_button_xpath));
+
+    // Fill in and save level 2 IEF form.
+    $assert_session->elementExists('xpath', $nested_title_field_xpath)->setValue('Level 2');
+    $assert_session->elementExists('xpath', $first_create_node_button_xpath)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_edit_button_xpath));
+
+    // Save the top level entity.
+    $assert_session->elementExists('xpath', $top_title_field_xpath)->setValue('Level 1');
+    $this->waitForElementRemoved('xpath', $first_edit_button_xpath);
+    $page->pressButton('Save');
+
+    // Re-edit the created node to test for revisions.
+    $node = $this->drupalGetNodeByTitle('Level 1');
+    $this->drupalGet('node/' . $node->id() . '/edit');
+
+    // Open up level 2 and 3 IEF forms.
+    $assert_session->elementExists('xpath', $first_edit_button_xpath)->press();
+    $this->waitForElementRemoved('xpath', $first_edit_button_xpath);
+    $assert_session->elementExists('xpath', $first_edit_button_xpath)->press();
+
+    // Change level 3 IEF node title.
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $double_nested_title_field_xpath));
+    $assert_session->elementExists('xpath', $double_nested_title_field_xpath)->setValue('Level 3.1');
+    $assert_session->elementExists('xpath', $first_update_button_xpath)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_edit_button_xpath));
+
+    // Change level 2 IEF node title.
+    $assert_session->elementExists('xpath', $nested_title_field_xpath)->setValue('Level 2.1');
+    $assert_session->elementExists('xpath', $first_update_button_xpath)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_edit_button_xpath));
+
+    // Save the top level entity.
+    $assert_session->elementExists('xpath', $top_title_field_xpath)->setValue('Level 1.1');
+    $this->waitForElementRemoved('xpath', $first_edit_button_xpath);
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1.1 has been updated.');
+    $assert_session->pageTextContains('Level 2.1');
+    $assert_session->pageTextContains('Level 3.1');
+
+    // Load the current revision id of the Level 2 node.
+    $node_level_2 = $this->drupalGetNodeByTitle('Level 2.1');
+    $node_level_2_vid = $node_level_2->getLoadedRevisionId();
+
+    // Load the current revision id of the Level 3 node.
+    $node_level_3 = $this->drupalGetNodeByTitle('Level 3.1');
+    $node_level_3_vid = $node_level_3->getLoadedRevisionId();
+
+    // Re-edit the created node to test for revisions.
+    $this->drupalGet('node/' . $node->id() . '/edit');
+
+    // Open up level 2 and 3 IEF forms.
+    $assert_session->elementExists('xpath', $first_edit_button_xpath)->press();
+    $this->waitForElementRemoved('xpath', $first_edit_button_xpath);
+    $assert_session->elementExists('xpath', $first_edit_button_xpath)->press();
+
+    // Change level 3 IEF node title.
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $double_nested_title_field_xpath));
+    $assert_session->elementExists('xpath', $double_nested_title_field_xpath)->setValue('Level 3.2');
+    $assert_session->elementExists('xpath', $first_update_button_xpath)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_edit_button_xpath));
+
+    // Change level 2 IEF node title.
+    $assert_session->elementExists('xpath', $nested_title_field_xpath)->setValue('Level 2.2');
+    $assert_session->elementExists('xpath', $first_update_button_xpath)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_edit_button_xpath));
+
+    // Save the top level entity.
+    $assert_session->elementExists('xpath', $top_title_field_xpath)->setValue('Level 1.2');
+    $this->waitForElementRemoved('xpath', $first_edit_button_xpath);
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1.2 has been updated.');
+    $assert_session->pageTextContains('Level 2.2');
+    $assert_session->pageTextContains('Level 3.2');
+
+    // Clear node cache.
+    $this->container->get('entity_type.manager')
+      ->getStorage('node')
+      ->resetCache();
+
+    // Load the current revision id of the Level 2 node.
+    $node_level_2 = $this->drupalGetNodeByTitle('Level 2.2');
+    $node_level_2_vid_new = $node_level_2->getLoadedRevisionId();
+
+    // Assert that a new revision created.
+    $this->assertNotEqual($node_level_2_vid, $node_level_2_vid_new);
+
+    // Load the current revision id of the Level 3 node.
+    $node_level_3 = $this->drupalGetNodeByTitle('Level 3.2');
+    $node_level_3_vid_new = $node_level_3->getLoadedRevisionId();
+
+    // Assert that no new revision created.
+    $this->assertEqual($node_level_3_vid, $node_level_3_vid_new);
+  }
+
+  /**
+   * Tests saving entity revision with test entity that has no bundle.
+   */
+  public function testRevisionsWithTestEntityNoBundle() {
+    // Get the xpath selectors for the fields in this test.
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $name_field_xpath = $this->getXpathForNthInputByLabelText('Name', 1);
+
+    // Get the xpath selectors for the buttons in this test.
+    $first_add_new_no_bundle_node_button = $this->getXpathForButtonWithValue('Add new entity test without bundle', 1);
+    $first_no_bundle_create_node_button = $this->getXpathForButtonWithValue('Create entity test without bundle', 1);
+    $first_no_bundle_node_edit_button = $this->getXpathForButtonWithValue('Edit', 1);
+    $first_no_bundle_update_node_button = $this->getXpathForButtonWithValue('Update entity test without bundle', 1);
+
+    $this->drupalGet($this->formContentAddUrl);
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    // Open up test entity with no bundle IEF form.
+    $assert_session->elementExists('xpath', $first_add_new_no_bundle_node_button)->press();
+    $this->waitForElementRemoved('xpath', $first_add_new_no_bundle_node_button);
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_no_bundle_create_node_button));
+
+    // Save level 2 test entity without bundle IEF form.
+    $assert_session->elementExists('xpath', $name_field_xpath)->setValue('Level 2 entity without bundle');
+    $assert_session->elementExists('xpath', $first_no_bundle_create_node_button)->press();
+    $this->waitForElementRemoved('xpath', $first_add_new_no_bundle_node_button);
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_no_bundle_node_edit_button));
+
+    // Save the top level entity.
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Level 1');
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1 has been created.');
+    $assert_session->pageTextContains('Level 2 entity without bundle');
+
+    // Load the new revision id of the entity.
+    $entity_no_bundle = $this->container->get('entity_type.manager')
+      ->getStorage('entity_test_no_bundle')
+      ->loadByProperties(['name' => 'Level 2 entity without bundle']);
+    $entity = reset($entity_no_bundle);
+    $entity_no_bundle_vid = $entity->getLoadedRevisionId();
+
+    // Re-edit the created node to test for revisions.
+    $node = $this->drupalGetNodeByTitle('Level 1');
+    $this->drupalGet('node/' . $node->id() . '/edit');
+
+    // Open up test entity with no bundle IEF form for editing.
+    $assert_session->elementExists('xpath', $first_no_bundle_node_edit_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_no_bundle_update_node_button));
+
+    // Change test entity with no bundle title.
+    $assert_session->elementExists('xpath', $name_field_xpath)->setValue('Level 2.1 entity without bundle');
+    $assert_session->elementExists('xpath', $first_no_bundle_update_node_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $first_no_bundle_node_edit_button));
+
+    // Save the top level entity.
+    $page->fillField('title[0][value]', 'Level 1.1');
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1.1 has been updated.');
+    $assert_session->pageTextContains('Level 2.1 entity without bundle');
+
+    // Reload the new revision id of the entity.
+    $this->container->get('entity_type.manager')
+      ->getStorage('entity_test_no_bundle')
+      ->resetCache();
+    $entity_no_bundle = $this->container->get('entity_type.manager')
+      ->getStorage('entity_test_no_bundle')
+      ->load($entity->id());
+    $entity_no_bundle_vid_new = $entity_no_bundle->getLoadedRevisionId();
+
+    // Assert that new revision was created.
+    $this->assertNotEqual($entity_no_bundle_vid, $entity_no_bundle_vid_new);
+  }
+
+}
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetTest.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetTest.php
new file mode 100644
index 0000000000..71dbf36606
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ComplexWidgetTest.php
@@ -0,0 +1,909 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+use Drupal\node\Entity\Node;
+use Drupal\node\NodeInterface;
+use Drupal\Tests\TestFileCreationTrait;
+
+/**
+ * IEF complex field widget tests.
+ *
+ * @group inline_entity_form
+ */
+class ComplexWidgetTest extends InlineEntityFormTestBase {
+
+  use TestFileCreationTrait {
+    getTestFiles as drupalGetTestFiles;
+  }
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'inline_entity_form_test',
+    'field',
+    'field_ui',
+  ];
+
+  /**
+   * URL to add new content.
+   *
+   * @var string
+   */
+  protected $formContentAddUrl;
+
+  /**
+   * Entity form display storage.
+   *
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
+   */
+  protected $entityFormDisplayStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'create ief_reference_type content',
+      'create ief_test_nested1 content',
+      'create ief_test_nested2 content',
+      'create ief_test_nested3 content',
+      'edit any ief_reference_type content',
+      'delete any ief_reference_type content',
+      'create ief_test_complex content',
+      'edit any ief_test_complex content',
+      'delete any ief_test_complex content',
+      'edit any ief_test_nested1 content',
+      'edit any ief_test_nested2 content',
+      'edit any ief_test_nested3 content',
+      'view own unpublished content',
+      'administer content types',
+    ]);
+    $this->drupalLogin($this->user);
+
+    $this->formContentAddUrl = 'node/add/ief_test_complex';
+    $this->entityFormDisplayStorage = $this->container->get('entity_type.manager')->getStorage('entity_form_display');
+  }
+
+  /**
+   * Tests if form behaves correctly when field is empty.
+   */
+  public function testEmptyField() {
+    // Get the xpath selectors for the input fields in this test.
+    $inner_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $first_name_field_xpath = $this->getXpathForNthInputByLabelText('First name', 1);
+    $last_name_field_xpath = $this->getXpathForNthInputByLabelText('Last name', 1);
+
+    $assert_session = $this->assertSession();
+    // Don't allow addition of existing nodes.
+    $this->updateSetting('allow_existing', FALSE);
+    $this->drupalGet($this->formContentAddUrl);
+
+    // Assert title field on inline form exists.
+    $assert_session->elementExists('xpath', $inner_title_field_xpath);
+    // Assert first name field on inline form exists.
+    $assert_session->elementExists('xpath', $first_name_field_xpath);
+    // Assert last name field on inline form exists.
+    $assert_session->elementExists('xpath', $last_name_field_xpath);
+    $assert_session->buttonExists('Create node');
+
+    // Allow addition of existing nodes.
+    $this->updateSetting('allow_existing', TRUE);
+
+    // Asserts 'Add new node' form elements.
+    $this->drupalGet($this->formContentAddUrl);
+    $multi_fieldset = $assert_session
+      ->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    // Assert title field does not appear.
+    $assert_session->elementNotExists('xpath', $inner_title_field_xpath);
+    // Assert first name field does not appear.
+    $assert_session->elementNotExists('xpath', $first_name_field_xpath);
+    // Assert last name field does not appear.
+    $assert_session->elementNotExists('xpath', $last_name_field_xpath);
+    $assert_session->buttonExists('Add existing node', $multi_fieldset);
+    // Now submit 'Add new node' button in the 'Multiple nodes' fieldset.
+    $multi_fieldset->pressButton('Add new node');
+    // Assert title field on inline form exists.
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $inner_title_field_xpath));
+    // Assert first name field on inline form exists.
+    $assert_session->elementExists('xpath', $first_name_field_xpath);
+    // Assert second name field on inline form exists.
+    $assert_session->elementExists('xpath', $last_name_field_xpath);
+    $assert_session->buttonExists('Create node');
+    $assert_session->buttonExists('Cancel');
+
+    // Asserts 'Add existing node' form elements.
+    $this->drupalGet($this->formContentAddUrl);
+    $multi_fieldset = $assert_session->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $multi_fieldset->pressButton('Add existing node');
+    // Assert existing entity reference autocomplete field appears.
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $this->getXpathForAutoCompleteInput()));
+    $assert_session->buttonExists('Add node');
+    $assert_session->buttonExists('Cancel');
+  }
+
+  /**
+   * Tests creation of entities.
+   */
+  public function testEntityCreation() {
+    // Get the xpath selectors for the input fields in this test.
+    $first_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $inner_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $first_name_field_xpath = $this->getXpathForNthInputByLabelText('First name', 1);
+    $last_name_field_xpath = $this->getXpathForNthInputByLabelText('Last name', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    // Allow addition of existing nodes.
+    $this->updateSetting('allow_existing', TRUE);
+
+    $this->drupalGet($this->formContentAddUrl);
+    $multi_fieldset = $assert_session
+      ->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $multi_fieldset->pressButton('Add new node');
+    $this->assertNotEmpty($create_node_button = $assert_session->waitForButton('Create node'));
+    $create_node_button->press();
+    $this->assertNotEmpty($assert_session->waitForElement('css', 'div[data-drupal-messages]'));
+    $assert_session->pageTextContains('First name field is required.');
+    $assert_session->pageTextContains('Last name field is required.');
+    $assert_session->pageTextContains('Title field is required.');
+
+    // Create ief_reference_type node in IEF.
+    $this->drupalGet($this->formContentAddUrl);
+    $multi_fieldset = $assert_session
+      ->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $multi_fieldset->pressButton('Add new node');
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $inner_title_field_xpath));
+    $assert_session->elementExists('xpath', $inner_title_field_xpath)->setValue('Some reference');
+    $assert_session->elementExists('xpath', $first_name_field_xpath)->setValue('John');
+    $assert_session->elementExists('xpath', $last_name_field_xpath)->setValue('Doe');
+    $page->pressButton('Create node');
+    $this->assertNotEmpty($assert_session->waitForElement('css', '.ief-row-entity'));
+
+    // Tests if correct fields appear in the table.
+    $assert_session->elementTextContains('css', '.ief-row-entity .inline-entity-form-node-label', 'Some reference');
+    $assert_session->elementTextContains('css', '.ief-row-entity .inline-entity-form-node-status', 'Published');
+
+    // Tests if edit and remove buttons appear.
+    $multi_fieldset = $assert_session
+      ->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $assert_session->buttonExists('Edit', $multi_fieldset);
+    $assert_session->buttonExists('Remove', $multi_fieldset);
+
+    // Test edit functionality.
+    $assert_session->buttonExists('Edit', $multi_fieldset)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $inner_title_field_xpath));
+    $assert_session->elementExists('xpath', $inner_title_field_xpath)->setValue('Some changed reference');
+    $page->pressButton('Update node');
+    $this->waitForRowByTitle('Some changed reference');
+    // Tests if correct fields appear in the table.
+    $assert_session->elementTextContains('css', '.ief-row-entity .inline-entity-form-node-label', 'Some changed reference');
+    $assert_session->elementTextContains('css', '.ief-row-entity .inline-entity-form-node-status', 'Published');
+    // Tests if edit and remove buttons appear.
+    $multi_fieldset = $assert_session
+      ->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $assert_session->buttonExists('Edit', $multi_fieldset);
+    $assert_session->buttonExists('Remove', $multi_fieldset);
+
+    // Make sure unrelated AJAX submit doesn't save the referenced entity.
+    // @todo restore this test.
+    // @see https://www.drupal.org/project/inline_entity_form/issues/3088453
+    $assert_session->elementExists('xpath', $first_title_field_xpath)->setValue('Some title');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex Some title has been created.');
+
+    // Checks values of created entities.
+    $node = $this->drupalGetNodeByTitle('Some changed reference');
+    $this->assertNotEmpty($node, 'Created ief_reference_type node ' . $node->label());
+    $this->assertSame('John', $node->get('first_name')->value, 'First name in reference node set to John');
+    $this->assertSame('Doe', $node->get('last_name')->value, 'Last name in reference node set to Doe');
+
+    $parent_node = $this->drupalGetNodeByTitle('Some title');
+    $this->assertNotEmpty($parent_node, 'Created ief_test_complex node ' . $parent_node->label());
+    $this->assertSame($node->id(), $parent_node->multi->target_id, 'Reference node id set to ' . $node->id());
+  }
+
+  /**
+   * Tests the entity creation with different bundles nested in each other.
+   *
+   * Ief_test_nested1 -> ief_test_nested2 -> ief_test_nested3
+   */
+  public function testNestedEntityCreationWithDifferentBundlesAjaxSubmit() {
+    // Get the xpath selectors for the input fields in this test.
+    $top_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $double_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    foreach ([FALSE, TRUE] as $required) {
+      $this->setupNestedComplexForm($required);
+      $required_string = ($required) ? ' required' : ' unrequired';
+      $double_nested_title = 'Dream within a dream' . $required_string;
+      $nested_title = 'Dream' . $required_string;
+      $top_level_title = 'Reality' . $required_string;
+      $this->assertNotEmpty($field = $assert_session->waitForElement('xpath', $double_nested_title_field_xpath));
+      $field->setValue($double_nested_title);
+      $page->pressButton('Create node 3');
+      $this->waitForRowByTitle($double_nested_title);
+
+      // Assert title of second nested node found.
+      $this->assertNoNodeByTitle($double_nested_title, 'Second nested entity is not saved yet.');
+
+      $assert_session->elementExists('xpath', $nested_title_field_xpath)->setValue($nested_title);
+      $page->pressButton('Create node 2');
+      $this->waitForRowByTitle($nested_title);
+      $this->assertNoNodeByTitle($nested_title, 'First nested entity is not saved yet.');
+
+      $assert_session->elementExists('xpath', $top_title_field_xpath)->setValue($top_level_title);
+      $page->pressButton('Save');
+      $assert_session->pageTextContains("IEF test nested 1 $top_level_title has been created.");
+      $top_level_node = $this->drupalGetNodeByTitle($top_level_title);
+      $this->assertNotEmpty($top_level_node);
+      $nested_node = $this->drupalGetNodeByTitle($nested_title);
+      $this->assertNotEmpty($nested_node);
+      $double_nested_node = $this->drupalGetNodeByTitle($double_nested_title);
+      $this->assertNotEmpty($double_nested_node);
+      $this->checkNestedNodes($top_level_node, $nested_node, $double_nested_node);
+    }
+  }
+
+  /**
+   * Tests the entity creation with different bundles nested in each other.
+   *
+   * Ief_test_nested1 -> ief_test_nested2 -> ief_test_nested3
+   */
+  public function testNestedEntityCreationWithDifferentBundlesNoAjaxSubmit() {
+    // Get the xpath selectors for the input fields in this test.
+    $top_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $double_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    foreach ([FALSE, TRUE] as $required) {
+      $this->setupNestedComplexForm($required);
+      $required_string = ($required) ? ' required' : ' unrequired';
+      $double_nested_title = 'Dream within a dream' . $required_string;
+      $nested_title = 'Dream' . $required_string;
+      $top_level_title = 'Reality' . $required_string;
+      $assert_session->elementExists('xpath', $top_title_field_xpath)->setValue($top_level_title);
+      $assert_session->elementExists('xpath', $nested_title_field_xpath)->setValue($nested_title);
+      $assert_session->elementExists('xpath', $double_nested_title_field_xpath)->setValue($double_nested_title);
+      $page->pressButton('Save');
+      $assert_session->pageTextContains("IEF test nested 1 $top_level_title has been created.");
+      $top_level_node = $this->drupalGetNodeByTitle($top_level_title);
+      $this->assertNotEmpty($top_level_node);
+      $nested_node = $this->drupalGetNodeByTitle($nested_title);
+      $this->assertNotEmpty($nested_node);
+      $double_nested_node = $this->drupalGetNodeByTitle($double_nested_title);
+      $this->assertNotEmpty($double_nested_node);
+      $this->checkNestedNodes($top_level_node, $nested_node, $double_nested_node);
+    }
+  }
+
+  /**
+   * Tests if editing and removing entities work.
+   */
+  public function testEntityEditingAndRemoving() {
+    // Get the xpath selectors for the fields in this test.
+    $inner_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $first_name_field_xpath = $this->getXpathForNthInputByLabelText('First name', 1);
+    $last_name_field_xpath = $this->getXpathForNthInputByLabelText('Last name', 1);
+    $first_delete_checkbox_xpath = $this->getXpathForNthInputByLabelText('Delete this node from the system.', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    // Allow addition of existing nodes.
+    $this->updateSetting('allow_existing', TRUE);
+
+    // Create three ief_reference_type entities.
+    $referenceNodes = $this->createReferenceContent(3);
+    $this->drupalCreateNode([
+      'type' => 'ief_test_complex',
+      'title' => 'Some title',
+      'multi' => array_values($referenceNodes),
+    ]);
+    /** @var \Drupal\node\NodeInterface $parent_node */
+    $parent_node = $this->drupalGetNodeByTitle('Some title');
+
+    // Edit the second entity.
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+    $assert_session->elementExists('xpath', '(//input[@value="Edit"])[2]')->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $inner_title_field_xpath));
+    $assert_session->elementExists('xpath', $first_name_field_xpath)->setValue('John');
+    $assert_session->elementExists('xpath', $last_name_field_xpath)->setValue('Doe');
+    $page->pressButton('Update node');
+    $this->assertNotEmpty($this->waitForElementRemoved('css', 'div[data-drupal-selector="edit-multi-form-inline-entity-form-entities-1-form"]'));
+    $this->waitForRowByTitle('Some reference 2');
+
+    // Save the ief_test_complex node.
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex Some title has been updated.');
+
+    // Checks values of changed entities.
+    $node = $this->drupalGetNodeByTitle('Some reference 2', TRUE);
+    $this->assertSame('John', $node->first_name->value, 'First name in reference node changed to John');
+    $this->assertSame('Doe', $node->last_name->value, 'Last name in reference node changed to Doe');
+
+    // Delete the second entity.
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 3);
+    $assert_session->elementExists('xpath', '(//input[@value="Remove"])[2]')->press();
+    $this->assertNotEmpty($confirm_checkbox = $assert_session->waitForElement('xpath', $first_delete_checkbox_xpath));
+    $assert_session->pageTextContains('Are you sure you want to remove Some reference 2?');
+    $confirm_checkbox->check();
+    $assert_session->elementExists('xpath', '(//input[@value="Remove"])[2]')->press();
+    $this->waitForRowRemovedByTitle('Some reference 2');
+    // Assert two rows show, instead of 3.
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 2);
+
+    // Save the ief_test_complex node.
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex Some title has been updated.');
+
+    $deleted_node = $this->drupalGetNodeByTitle('Some reference 2');
+    $this->assertEmpty($deleted_node, 'The inline entity was deleted from the site.');
+
+    // Checks that entity does nor appear in IEF.
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+    // Assert 2 rows show, instead of 3.
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 2);
+    $this->assertRowByTitle('Some reference 1');
+    $this->assertNoRowByTitle('Some reference 2');
+    $this->assertRowByTitle('Some reference 3');
+
+    // Delete the third entity reference only, don't delete the node. The third
+    // entity now is second referenced entity because the second one was deleted
+    // in previous step.
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 2);
+    $assert_session->elementExists('xpath', '(//input[@value="Remove"])[2]')->press();
+    $this->assertNotEmpty($confirm_checkbox = $assert_session->waitForElement('xpath', $first_delete_checkbox_xpath));
+    $assert_session->pageTextContains('Are you sure you want to remove Some reference 3?');
+    $assert_session->elementExists('xpath', '(//input[@value="Remove"])[2]')->press();
+    $this->waitForRowRemovedByTitle('Some reference 3');
+    // Assert only one row displays.
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 1);
+    $this->assertRowByTitle('Some reference 1');
+    $this->assertNoRowByTitle('Some reference 2');
+    $this->assertNoRowByTitle('Some reference 3');
+
+    // Save the ief_test_complex node.
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex Some title has been updated.');
+
+    // Checks that entity is not deleted.
+    $node = $this->drupalGetNodeByTitle('Some reference 3');
+    $this->assertNotEmpty($node, 'Reference node not deleted');
+  }
+
+  /**
+   * Tests if referencing existing entities work.
+   */
+  public function testReferencingExistingEntities() {
+    // Get the xpath selectors for the input fields in this test.
+    $node_field_xpath = $this->getXpathForNthInputByLabelText('Node', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    // Allow addition of existing nodes.
+    $this->updateSetting('allow_existing', TRUE);
+
+    // Create three ief_reference_type entities.
+    $referenceNodes = $this->createReferenceContent(3);
+
+    // Create a node for every bundle available.
+    $bundle_nodes = $this->createNodeForEveryBundle();
+
+    // Create ief_test_complex node with first ief_reference_type node and first
+    // node from bundle nodes.
+    $this->drupalCreateNode([
+      'type' => 'ief_test_complex',
+      'title' => 'Some title',
+      'multi' => [1],
+      'all_bundles' => key($bundle_nodes),
+    ]);
+    // Remove first node since we already added it.
+    unset($bundle_nodes[key($bundle_nodes)]);
+
+    $parent_node = $this->drupalGetNodeByTitle('Some title', TRUE);
+
+    // Add remaining existing reference nodes.
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+    for ($i = 2; $i <= 3; $i++) {
+      $this->openMultiExistingForm();
+      $title = 'Some reference ' . $i;
+      $assert_session->elementExists('xpath', $node_field_xpath)->setValue($title . ' (' . $referenceNodes[$title] . ')');
+      $page->pressButton('Add node');
+      $this->waitForRowByTitle($title);
+    }
+    // Add all remaining nodes from all bundles.
+    foreach ($bundle_nodes as $id => $title) {
+      $all_bundles_fieldset = $assert_session
+        ->elementExists('css', 'fieldset[data-drupal-selector="edit-all-bundles"]');
+      $assert_session->buttonExists('Add existing node', $all_bundles_fieldset)->press();
+      $this->assertNotEmpty($assert_session->waitForElement('xpath', $node_field_xpath));
+      $assert_session->elementExists('xpath', $node_field_xpath)->setValue($title . ' (' . $id . ')');
+      $page->pressButton('Add node');
+      $this->waitForRowByTitle($title);
+    }
+    // Save the node.
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex Some title has been updated.');
+
+    // Check if entities are referenced.
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+
+    $assert_session->elementsCount('css', 'fieldset[data-drupal-selector="edit-multi"] tr.ief-row-entity', 3);
+    $this->assertRowByTitle('Some reference 1');
+    $this->assertRowByTitle('Some reference 2');
+    $this->assertRowByTitle('Some reference 3');
+
+    // Check if all remaining nodes from all bundles are referenced.
+    $assert_session->elementsCount('css', 'fieldset[data-drupal-selector="edit-all-bundles"] tr.ief-row-entity', 12);
+    foreach ($bundle_nodes as $id => $title) {
+      $this->assertRowByTitle($title);
+    }
+  }
+
+  /**
+   * Tests if referencing an existing entity works without submitting the form.
+   */
+  public function testReferencingExistingEntitiesNoSubmit() {
+    // Get the xpath selectors for the input fields in this test.
+    $node_field_xpath = $this->getXpathForNthInputByLabelText('Node', 1);
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+
+    // Allow addition of existing nodes.
+    $this->updateSetting('allow_existing', TRUE);
+    $title = $this->randomMachineName();
+
+    $this->drupalCreateNode([
+      'type' => 'ief_reference_type',
+      'title' => $title,
+      'first_name' => $this->randomMachineName(),
+      'last_name' => $this->randomMachineName(),
+    ]);
+    $node = $this->drupalGetNodeByTitle($title);
+    $this->assertNotEmpty($node, 'Created ief_reference_type node "' . $node->label() . '"');
+
+    $this->drupalGet($this->formContentAddUrl);
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    $this->openMultiExistingForm();
+    $assert_session->elementExists('xpath', $node_field_xpath)->setValue($node->getTitle() . ' (' . $node->id() . ')');
+    $parent_title = $this->randomMachineName();
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue($parent_title);
+    $page->pressButton('Save');
+    $assert_session->pageTextContains("IEF test complex $parent_title has been created.");
+    $assert_session->pageTextNotContains('This value should not be null.');
+    $node = $this->drupalGetNodeByTitle($parent_title);
+    $this->assertNotEmpty($node, 'Created ief_reference_type node.');
+  }
+
+  /**
+   * Test if invalid values get correct validation messages.
+   *
+   * Tests validation in reference existing entity form.  It also checks if
+   * existing entity reference form can be canceled.
+   */
+  public function testReferenceExistingValidation() {
+    // Get the xpath selectors for the input fields in this test.
+    $node_field_xpath = $this->getXpathForNthInputByLabelText('Node', 1);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $this->updateSetting('allow_existing', TRUE);
+
+    $this->drupalGet('node/add/ief_test_complex');
+    $this->checkExistingValidationExpectation('', 'Node field is required.');
+    $this->checkExistingValidationExpectation('Fake Title', 'There are no entities matching "Fake Title"');
+    // Check adding nodes that cannot be referenced by this field.
+    foreach ($this->createNodeForEveryBundle() as $id => $title) {
+      $node = Node::load($id);
+      if ($node->bundle() !== 'ief_reference_type') {
+        $this->checkExistingValidationExpectation("$title ($id)", "The referenced entity (node: $id) does not exist.");
+      }
+    }
+
+    foreach ($this->createReferenceContent(2) as $title => $id) {
+      $this->openMultiExistingForm();
+      $current_title = "$title ($id)";
+      $assert_session->elementExists('xpath', $node_field_xpath)->setValue($current_title);
+      $page->pressButton('Add node');
+      $this->waitForRowByTitle($title);
+      $assert_session->elementNotExists('xpath', $node_field_xpath);
+      // Try to add the same node again.
+      $this->checkExistingValidationExpectation($current_title, 'The selected node has already been added.');
+    }
+  }
+
+  /**
+   * Tests if duplicating entities works.
+   */
+  public function testDuplicatingEntities() {
+    // Get the xpath selectors for the input fields in this test.
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $first_name_field_xpath = $this->getXpathForNthInputByLabelText('First name', 1);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $this->updateSetting('allow_duplicate', TRUE);
+
+    $referenceNodes = $this->createReferenceContent(2);
+    $this->drupalCreateNode([
+      'type' => 'ief_test_complex',
+      'title' => 'Some title',
+      'multi' => array_values($referenceNodes),
+    ]);
+    /** @var \Drupal\node\NodeInterface $parent_node */
+    $parent_node = $this->drupalGetNodeByTitle('Some title');
+
+    $this->drupalGet('node/' . $parent_node->id() . '/edit');
+    $this->assertNotEmpty($multi_fieldset = $assert_session->waitForElement('css', 'fieldset[data-drupal-selector="edit-multi"]'));
+    $assert_session->buttonExists('Duplicate', $multi_fieldset)->press();
+    $this->assertNotEmpty($create_node_button = $assert_session->waitForButton('Duplicate node'));
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Duplicate!');
+    $assert_session->elementExists('xpath', $first_name_field_xpath)->setValue('Bojan');
+    $create_node_button->press();
+
+    $this->waitForRowByTitle('Duplicate!');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 3);
+    $this->assertRowByTitle('Some reference 1');
+    $this->assertRowByTitle('Some reference 2');
+    $this->assertRowByTitle('Duplicate!');
+    $page->pressButton('Save');
+    $duplicate = $this->drupalGetNodeByTitle('Duplicate!');
+    $this->assertNotEmpty($duplicate, 'Duplicate node created.');
+    $this->assertSame('Bojan', $duplicate->first_name->value);
+  }
+
+  /**
+   * Tests if a referenced content can be edited.
+   *
+   * When the referenced content is newer than the referencing parent node,
+   * test if a referenced content can be edited.
+   */
+  public function testEditedInlineEntityValidation() {
+    // Get the xpath selectors for the input fields in this test.
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $this->updateSetting('allow_existing', TRUE);
+
+    // Create referenced content.
+    $referenced_nodes = $this->createReferenceContent(1);
+
+    // Create first referencing node.
+    $this->drupalCreateNode([
+      'type' => 'ief_test_complex',
+      'title' => 'First referencing node',
+      'multi' => array_values($referenced_nodes),
+    ]);
+    $first_node = $this->drupalGetNodeByTitle('First referencing node');
+
+    // Create second referencing node.
+    $this->drupalCreateNode([
+      'type' => 'ief_test_complex',
+      'title' => 'Second referencing node',
+      'multi' => array_values($referenced_nodes),
+    ]);
+    $second_node = $this->drupalGetNodeByTitle('Second referencing node');
+
+    // Edit referenced content in first node.
+    $this->drupalGet('node/' . $first_node->id() . '/edit');
+    $page->pressButton('Edit');
+    $this->assertNotEmpty($nested_title = $assert_session->waitForElement('xpath', $nested_title_field_xpath));
+    $nested_title->setValue('Some reference updated');
+    $page->pressButton('Update node');
+    $this->waitForRowByTitle('Some reference updated');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 1);
+
+    // Save the first node after editing the reference.
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue('First node updated');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex First node updated has been updated.');
+
+    // The changed value of the referenced content is now newer than the
+    // changed value of the second node.
+    // Edit referenced content in second node.
+    $this->drupalGet('node/' . $second_node->id() . '/edit');
+
+    // Edit referenced node.
+    $page->pressButton('Edit');
+    $this->assertNotEmpty($nested_title = $assert_session->waitForElement('xpath', $nested_title_field_xpath));
+    $nested_title->setValue('Some reference updated the second time');
+    $page->pressButton('Update node');
+    $this->waitForRowByTitle('Some reference updated the second time');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 1);
+
+    // Save the second node after editing the reference.
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Second node updated');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex Second node updated has been updated.');
+
+    // Check if the referenced content could be edited.
+    $assert_session->pageTextNotContains('The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.');
+  }
+
+  /**
+   * Checks that nested IEF entity references can be edited and saved.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   Top level node of type ief_test_nested1 to check.
+   */
+  protected function checkNestedNodeEditing(NodeInterface $node) {
+    // Get the xpath selectors for the input fields in this test.
+    $double_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    $nested_node = $node->test_ref_nested1->entity;
+    $double_nested_node = $nested_node->test_ref_nested2->entity;
+
+    $this->drupalGet("node/{$node->id()}/edit");
+    $this->assertRowByTitle($nested_node->label());
+    $page->pressButton('Edit');
+    $this->waitForRowByTitle($double_nested_node->label());
+    $page->pressButton('Edit');
+    $this->assertNotEmpty($assert_session->waitforButton('Update node 3'));
+    $double_nested_node_update_title = $double_nested_node->getTitle() . ' - updated';
+    $assert_session->elementExists('xpath', $double_nested_title_field_xpath)->setValue($double_nested_node_update_title);
+    // Close the double nested IEF form.
+    $page->pressButton('Update node 3');
+    $this->waitForRowByTitle($double_nested_node_update_title);
+
+    // Close the nested IEF form.
+    $page->pressButton('Update node 2');
+    $this->assertNotEmpty($this->waitForElementRemoved('css', 'div[data-drupal-selector="edit-test-ref-nested1-form-inline-entity-form-entities-0-form"]'));
+    $this->waitForRowByTitle($nested_node->label());
+    // Save the top level node.
+    $page->pressButton('Save');
+
+    $assert_session->pageTextContains('IEF test nested 1 ' . $node->label() . ' has been updated.');
+
+    // Verify the double nested node title change saved properly.
+    $this->drupalGet("node/{$node->id()}/edit");
+    $page->pressButton('Edit');
+    $this->waitForRowByTitle($double_nested_node_update_title);
+    $this->drupalGet("node/{$double_nested_node->id()}/edit");
+    $this->assertSame($double_nested_node_update_title, $assert_session->elementExists('xpath', $title_field_xpath)->getValue());
+  }
+
+  /**
+   * Creates ief_reference_type nodes which shall serve as reference nodes.
+   *
+   * @param int $numNodes
+   *   The number of nodes to create.
+   *
+   * @return array
+   *   Array of created node ids keyed by labels.
+   */
+  protected function createReferenceContent($numNodes = 3) {
+    $retval = [];
+    for ($i = 1; $i <= $numNodes; $i++) {
+      $this->drupalCreateNode([
+        'type' => 'ief_reference_type',
+        'title' => 'Some reference ' . $i,
+        'first_name' => 'First Name ' . $i,
+        'last_name' => 'Last Name ' . $i,
+      ]);
+      $node = $this->drupalGetNodeByTitle('Some reference ' . $i);
+      $this->assertNotEmpty($node, 'Created ief_reference_type node "' . $node->label() . '"');
+      $retval[$node->label()] = $node->id();
+    }
+    return $retval;
+  }
+
+  /**
+   * Updates an IEF setting and saves the underlying entity display.
+   *
+   * @param string $name
+   *   The name of the setting.
+   * @param mixed $value
+   *   The value to set.
+   */
+  protected function updateSetting($name, $value) {
+    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */
+    $display = $this->entityFormDisplayStorage->load('node.ief_test_complex.default');
+    $component = $display->getComponent('multi');
+    $component['settings'][$name] = $value;
+    $display->setComponent('multi', $component)->save();
+  }
+
+  /**
+   * Creates a node for every node bundle.
+   *
+   * @return array
+   *   Array of node titles keyed by ids.
+   */
+  protected function createNodeForEveryBundle() {
+    $retval = [];
+    $bundles = $this->container->get('entity_type.bundle.info')->getBundleInfo('node');
+    foreach ($bundles as $id => $value) {
+      $this->drupalCreateNode(['type' => $id, 'title' => $value['label']]);
+      $node = $this->drupalGetNodeByTitle($value['label']);
+      $this->assertNotEmpty($node, 'Created node "' . $node->label() . '"');
+      $retval[$node->id()] = $value['label'];
+    }
+    return $retval;
+  }
+
+  /**
+   * Set up the ief_test_nested1 node add form.
+   *
+   * Sets the nested fields' required settings.
+   * Gets the form.
+   * Opens the inline entity forms if they are not required.
+   *
+   * @param bool $required
+   *   Whether the fields are required.
+   */
+  protected function setupNestedComplexForm($required) {
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    /** @var \Drupal\Core\Field\FieldConfigInterface $ief_test_nested1 */
+    $this->fieldConfigStorage->load('node.ief_test_nested1.test_ref_nested1')
+      ->setRequired($required)
+      ->save();
+    /** @var \Drupal\Core\Field\FieldConfigInterface $ief_test_nested2 */
+    $this->fieldConfigStorage
+      ->load('node.ief_test_nested2.test_ref_nested2')
+      ->setRequired($required)
+      ->save();
+
+    $this->drupalGet('node/add/ief_test_nested1');
+
+    if (!$required) {
+      // Open inline forms if not required.
+      $page->pressButton('Add new node 2');
+      $this->assertNotEmpty($button = $assert_session->waitForButton('Add new node 3'));
+      $button->press();
+      $this->assertNotEmpty($assert_session->waitForButton('Create node 3'));
+    }
+
+  }
+
+  /**
+   * Opens the existing node form on the "multi" field.
+   */
+  protected function openMultiExistingForm() {
+    $assert_session = $this->assertSession();
+    $this->assertNotEmpty($multi_fieldset = $assert_session->waitForElement('css', 'fieldset[data-drupal-selector="edit-multi"]'));
+    $assert_session->buttonExists('Add existing node', $multi_fieldset)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('xpath', $this->getXpathForAutoCompleteInput()));
+  }
+
+  /**
+   * Check existing node field validation.
+   *
+   * Checks that an invalid value for an existing node will be display the
+   * expected error.
+   *
+   * @param string $existing_node_text
+   *   The text to enter into the existing node text field.
+   * @param string $expected_error
+   *   The error message that is expected to be shown.
+   */
+  protected function checkExistingValidationExpectation($existing_node_text, $expected_error) {
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $this->openMultiExistingForm();
+    $field = $assert_session->waitForElement('xpath', $this->getXpathForAutoCompleteInput());
+    $field->setValue($existing_node_text);
+    $page->pressButton('Add node');
+    $this->assertNotEmpty($assert_session->waitForText($expected_error));
+    $assert_session->buttonExists('Cancel')->press();
+    $this->assertNotEmpty($this->waitForElementRemoved('xpath', $this->getXpathForAutoCompleteInput()));
+  }
+
+  /**
+   * Tests create access on IEF Complex content type.
+   */
+  public function testComplexEntityCreate() {
+    // Get the xpath selectors for the input fields in this test.
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+
+    $user = $this->createUser([
+      'create ief_test_complex content',
+    ]);
+    $this->drupalLogin($user);
+
+    $this->drupalGet('node/add/ief_test_complex');
+    $assert_session = $this->assertSession();
+    $assert_session->fieldNotExists('all_bundles[actions][bundle]');
+    $assert_session->elementNotExists('xpath', $nested_title_field_xpath);
+
+    $user = $this->createUser([
+      'create ief_test_complex content',
+      'create ief_reference_type content',
+    ]);
+    $this->drupalLogin($user);
+
+    $this->drupalGet('node/add/ief_test_complex');
+    $assert_session->fieldExists('all_bundles[actions][bundle]');
+    $this->assertOption('edit-all-bundles-actions-bundle', 'ief_reference_type');
+    $this->assertOption('edit-all-bundles-actions-bundle', 'ief_test_complex');
+    $assert_session->elementExists('xpath', $nested_title_field_xpath);
+  }
+
+  /**
+   * Checks if nested nodes for ief_test_nested1 content are created.
+   *
+   * @param \Drupal\node\NodeInterface $top_level_node
+   *   The top level node.
+   * @param \Drupal\node\NodeInterface $nested_node
+   *   The second level node.
+   * @param \Drupal\node\NodeInterface $double_nested_node
+   *   The the third level node.
+   */
+  protected function checkNestedNodes(NodeInterface $top_level_node, NodeInterface $nested_node, NodeInterface $double_nested_node) {
+    // Check the type and title of the second level node.
+    if ($nested_node->id() == $top_level_node->test_ref_nested1->entity->id()) {
+      $this->assertEquals(1, $top_level_node->test_ref_nested1->count(), 'Only one nested node created');
+      $this->assertSame($top_level_node->test_ref_nested1->entity->label(), $nested_node->label(), "Nested node's title is correct.");
+      $this->assertSame('ief_test_nested2', $nested_node->bundle(), "Nested node's type is correct.");
+
+      // Check the type and title of the third level node.
+      if ($double_nested_node->id() == $nested_node->test_ref_nested2->entity->id()) {
+        $this->assertEquals(1, $nested_node->test_ref_nested2->count(), 'Only one node within a node within a node created.');
+        $this->assertSame($nested_node->test_ref_nested2->entity->label(), $double_nested_node->label(), "Node within a node within a node's title is correct.");
+        $this->assertSame('ief_test_nested3', $double_nested_node->bundle(), "Node within a node within a node's type is correct.");
+        $this->checkNestedNodeEditing($top_level_node);
+      }
+    }
+  }
+
+  /**
+   * Tests the separation of nested data.
+   *
+   * Using entity creation with different bundles nested in each other.
+   * Ief_test_nested1 -> ief_test_nested2 -> ief_test_nested3
+   *
+   * When creating a second ief_test_nested2 it should be empty and not be
+   * prefilled with the ief_test_nested3 of the first ief_test_nested2.
+   */
+  public function testSeparateNestedDataMultiValueFields() {
+    // Get the xpath selectors for the input fields in this test.
+    $top_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $double_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    foreach ([FALSE, TRUE] as $required) {
+      $this->setupNestedComplexForm($required);
+      $required_string = ($required) ? ' required' : ' unrequired';
+      $double_nested_title = 'Dream within a dream' . $required_string;
+      $nested_title = 'Dream' . $required_string;
+      $top_level_title = 'Reality' . $required_string;
+      $assert_session->elementExists('xpath', $top_title_field_xpath)
+        ->setValue($top_level_title);
+      $assert_session->elementExists('xpath', $nested_title_field_xpath)
+        ->setValue($nested_title);
+      $assert_session->elementExists('xpath', $double_nested_title_field_xpath)
+        ->setValue($double_nested_title);
+      $page->pressButton('Create node 3');
+      $assert_session->waitForButton('Add new node 3');
+      $page->pressButton('Create node 2');
+      $assert_session->waitForButton('Add new node 2');
+      $page->pressButton('Add new node 2');
+      $assert_session->waitForButton('Add new node 3');
+      // The new node 2 should be empty and not already have a
+      // double_nested_title present.
+      $this->assertNoRowByTitle($double_nested_title);
+    }
+  }
+
+}
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ElementWebTest.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ElementWebTest.php
new file mode 100644
index 0000000000..46c5d4ed76
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/ElementWebTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+/**
+ * Tests the IEF element on a custom form.
+ *
+ * @group inline_entity_form
+ */
+class ElementWebTest extends InlineEntityFormTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['inline_entity_form_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'create ief_simple_single content',
+      'edit any ief_test_custom content',
+      'view own unpublished content',
+      'administer nodes',
+    ]);
+
+    $this->drupalLogin($this->user);
+
+    $this->fieldStorageConfigStorage = $this->container
+      ->get('entity_type.manager')
+      ->getStorage('field_storage_config');
+  }
+
+  /**
+   * Tests IEF on a custom form.
+   */
+  public function testCustomForm() {
+    // Get the xpath selectors for the fields in this test.
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $positive_int_field_xpath = $this->getXpathForNthInputByLabelText('Positive int', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    foreach (['default', 'inline'] as $form_mode_possibility) {
+      $title = $this->randomMachineName();
+      $this->drupalGet("ief-test/$form_mode_possibility");
+      $assert_session->pageTextContains('Title');
+      $assert_session->pageTextContains('Positive int');
+      $this->checkFormDisplayFields("node.ief_test_custom.$form_mode_possibility", 'inline_entity_form');
+
+      $page->pressButton('Save');
+      $assert_session->pageTextNotContains("Created Content $title");
+      // @todo How do we test Chrome's HTML 5 validation?
+      // $assert_session->pageTextContains('Please fill out this field.');
+      // Fix in https://www.drupal.org/project/inline_entity_form/issues/3100883
+      $this->assertNoNodeByTitle($title);
+
+      $assert_session->elementExists('xpath', $title_field_xpath)->setValue($title);
+      $assert_session->elementExists('xpath', $positive_int_field_xpath)->setValue(-1);
+
+      $page->pressButton('Save');
+      $assert_session->pageTextNotContains("Created Content $title");
+      $this->assertNoNodeByTitle($title);
+
+      $assert_session->elementExists('xpath', $positive_int_field_xpath)->setValue(11);
+      $page->pressButton('Save');
+      $assert_session->pageTextContains("Created Content $title");
+      $this->assertNodeByTitle($title, 'ief_test_custom');
+      $node = $this->getNodeByTitle($title);
+
+      $this->drupalGet("ief-test/$form_mode_possibility/{$node->id()}");
+      // Assert node title appears in form.
+      $assert_session->elementExists('xpath', $title_field_xpath);
+      $this->checkFormDisplayFields("node.ief_test_custom.$form_mode_possibility", 'inline_entity_form');
+      $this->assertSame('11', $assert_session->elementExists('xpath', $positive_int_field_xpath)->getValue());
+      $assert_session->elementExists('xpath', $title_field_xpath)->setValue($title . ' - updated');
+      $page->pressButton('Update');
+      $this->assertNodeByTitle($title . ' - updated', 'ief_test_custom');
+    }
+  }
+
+}
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/InlineEntityFormTestBase.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/InlineEntityFormTestBase.php
new file mode 100644
index 0000000000..5f0625218c
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/InlineEntityFormTestBase.php
@@ -0,0 +1,319 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+
+/**
+ * Base Class for Inline Entity Form Tests.
+ */
+abstract class InlineEntityFormTestBase extends WebDriverTestBase {
+
+  /**
+   * User with permissions to create content.
+   *
+   * @var \Drupal\user\Entity\User
+   */
+  protected $user;
+
+  /**
+   * Field config storage.
+   *
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorage
+   */
+  protected $fieldStorageConfigStorage;
+
+  /**
+   * Field config storage.
+   *
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
+   */
+  protected $fieldConfigStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->fieldStorageConfigStorage = $this->container->get('entity_type.manager')->getStorage('field_storage_config');
+    $this->fieldConfigStorage = $this->container->get('entity_type.manager')->getStorage('field_config');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function prepareSettings() {
+    $drupal_version = (float) substr(\Drupal::VERSION, 0, 3);
+    if ($drupal_version < 8.8) {
+      // Fix entity_reference_autocomplete match_limit schema errors.
+      $this->strictConfigSchema = FALSE;
+    }
+    parent::prepareSettings();
+  }
+
+  /**
+   * Gets IEF button name.
+   *
+   * @param string $xpath
+   *   Xpath of the button.
+   *
+   * @return string
+   *   The name of the button.
+   */
+  protected function getButtonName($xpath) {
+    $retval = '';
+    /** @var \SimpleXMLElement[] $elements */
+    if ($elements = $this->xpath($xpath)) {
+      foreach ($elements[0]->attributes() as $name => $value) {
+        if ($name === 'name') {
+          $retval = $value;
+          break;
+        }
+      }
+    }
+    return $retval;
+  }
+
+  /**
+   * Passes if no node is found for the title.
+   *
+   * @param string $title
+   *   Node title to check.
+   * @param string $message
+   *   Message to display.
+   */
+  protected function assertNoNodeByTitle($title, $message = '') {
+    if (!$message) {
+      $message = "No node with title: $title";
+    }
+    $node = $this->getNodeByTitle($title, TRUE);
+
+    $this->assertEmpty($node, $message);
+  }
+
+  /**
+   * Passes if a node is found for the title.
+   *
+   * @param string $title
+   *   Node title to check.
+   * @param string $content_type
+   *   The content type to check.
+   * @param string $message
+   *   Message to display.
+   */
+  protected function assertNodeByTitle($title, $content_type = NULL, $message = '') {
+    if (!$message) {
+      $message = "Node with title found: $title";
+    }
+    $node = $this->getNodeByTitle($title, TRUE);
+    $this->assertNotEmpty($node, $message);
+    if ($content_type) {
+      $this->assertEqual($node->bundle(), $content_type, "Node is correct content type: $content_type");
+    }
+  }
+
+  /**
+   * Ensures that an entity with a specific label exists.
+   *
+   * @param string $label
+   *   The label of the entity.
+   * @param string $entity_type_id
+   *   The entity type ID.
+   * @param string $bundle
+   *   (optional) The bundle this entity should have.
+   */
+  protected function assertEntityByLabel($label, $entity_type_id = 'node', $bundle = NULL) {
+    $entity_type_manager = \Drupal::entityTypeManager();
+    $entity_type = $entity_type_manager->getDefinition($entity_type_id);
+    $label_key = $entity_type->getKey('label');
+    $bundle_key = $entity_type->getKey('bundle');
+
+    $query = $entity_type_manager->getStorage($entity_type_id)->getQuery();
+    $query->condition($label_key, $label);
+
+    if ($bundle && $bundle_key) {
+      $query->condition($bundle_key, $bundle);
+    }
+
+    $result = $query->execute();
+    $this->assertNotEmpty($result);
+  }
+
+  /**
+   * Checks for check correct fields on form displays.
+   *
+   * This checks based on exported config in the
+   * inline_entity_form_test module.
+   *
+   * @param string $form_display
+   *   The form display to check.
+   * @param string $prefix
+   *   The config prefix.
+   */
+  protected function checkFormDisplayFields($form_display, $prefix) {
+    $assert_session = $this->assertSession();
+    $form_display_fields = [
+      'node.ief_test_custom.default' => [
+        'expected' => [
+          '[title][0][value]',
+          '[uid][0][target_id]',
+          '[created][0][value][date]',
+          '[created][0][value][time]',
+          '[promote][value]',
+          '[sticky][value]',
+          '[positive_int][0][value]',
+        ],
+        'unexpected' => [],
+      ],
+      'node.ief_test_custom.inline' => [
+        'expected' => [
+          '[title][0][value]',
+          '[positive_int][0][value]',
+        ],
+        'unexpected' => [
+          '[uid][0][target_id]',
+          '[created][0][value][date]',
+          '[created][0][value][time]',
+          '[promote][value]',
+          '[sticky][value]',
+        ],
+      ],
+    ];
+
+    if (empty($form_display_fields[$form_display])) {
+      throw new \Exception('Form display not found: ' . $form_display);
+    }
+
+    $fields = $form_display_fields[$form_display];
+    foreach ($fields['expected'] as $expected_field) {
+      $assert_session->fieldExists($prefix . $expected_field);
+    }
+    foreach ($fields['unexpected'] as $unexpected_field) {
+      $assert_session->fieldNotExists($prefix . $unexpected_field, NULL);
+    }
+  }
+
+  /**
+   * Wait for an IEF table row to appear.
+   *
+   * @param string $title
+   *   The title of the row for which to wait.
+   */
+  protected function waitForRowByTitle($title) {
+    $this->assertNotEmpty($this->assertSession()->waitForElement('xpath', '//td[@class="inline-entity-form-node-label" and text()="' . $title . '"]'));
+  }
+
+  /**
+   * Wait for an IEF table row to disappear.
+   *
+   * @param string $title
+   *   The title of the row for which to wait.
+   */
+  protected function waitForRowRemovedByTitle($title) {
+    $this->assertNotEmpty($this->waitForElementRemoved('xpath', '//td[@class="inline-entity-form-node-label" and text()="' . $title . '"]'));
+  }
+
+  /**
+   * Asserts that an IEF table row exists.
+   *
+   * @param string $title
+   *   The title of the row to check.
+   *
+   * @return \Behat\Mink\Element\NodeElement
+   *   The <td> element containing the label for the IEF row.
+   */
+  protected function assertRowByTitle($title) {
+    $this->assertNotEmpty($element = $this->assertSession()->elementExists('xpath', '//td[@class="inline-entity-form-node-label" and text()="' . $title . '"]'));
+    return $element;
+  }
+
+  /**
+   * Asserts that an IEF table row does not exist.
+   *
+   * @param string $title
+   *   The title of the row to check.
+   */
+  protected function assertNoRowByTitle($title) {
+    $this->assertSession()->elementNotExists('xpath', '//td[@class="inline-entity-form-node-label" and text()="' . $title . '"]');
+  }
+
+  /**
+   * Returns xpath selector to the index-th input with label.
+   *
+   * Note: index starts at 1.
+   *
+   * @param string $label
+   *   The label text to select.
+   * @param int $index
+   *   The index of the input to select.
+   *
+   * @return string
+   *   The xpath selector for the input to select.
+   */
+  protected function getXpathForNthInputByLabelText($label, $index) {
+    return "(//*[@id=string((//label[.='{$label}']/@for)[{$index}])])";
+  }
+
+  /**
+   * Returns xpath selector to the first input with an auto-complete.
+   *
+   * @return string
+   *   The xpath selector for the first input with an auto-complete.
+   */
+  protected function getXpathForAutoCompleteInput() {
+    return '(//input[@data-autocomplete-path])';
+  }
+
+  /**
+   * Returns xpath selector to the index-th button with button text value.
+   *
+   * Note: index starts at 1.
+   *
+   * @param string @value
+   *   The text on the button to select.
+   * @param int $index
+   *   The index of the button to select.
+   *
+   * @return string
+   *   The xpath selector for the button to select.
+   */
+  protected function getXpathForButtonWithValue($value, $index) {
+    return "(//input[@type='submit' and @value='{$value}'][{$index}])";
+  }
+
+  /**
+   * Looks for the specified selector and returns TRUE when it is unavailable.
+   *
+   * @todo Remove when tests are running on Drupal 8.8. or greater. Then
+   * we can use $assert_session->waitForElementRemoved(). This is will be when
+   * Drupal 8.7 reaches EOL (which is when 8.9 is released in June 2020).
+   *
+   * @param string $selector
+   *   The selector engine name. See ElementInterface::findAll() for the
+   *   supported selectors.
+   * @param string|array $locator
+   *   The selector locator.
+   * @param int $timeout
+   *   (Optional) Timeout in milliseconds, defaults to 10000.
+   *
+   * @return bool
+   *   TRUE if not found, FALSE if found.
+   *
+   * @see \Drupal\FunctionalJavascriptTests\JSWebAssert::waitForElementRemoved
+   */
+  public function waitForElementRemoved($selector, $locator, $timeout = 10000) {
+    $page = $this->getSession()->getPage();
+
+    $result = $page->waitFor($timeout / 1000, function () use ($page, $selector, $locator) {
+      return !$page->find($selector, $locator);
+    });
+
+    return $result;
+  }
+
+}
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/SimpleWidgetTest.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/SimpleWidgetTest.php
new file mode 100644
index 0000000000..95df5451e1
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/SimpleWidgetTest.php
@@ -0,0 +1,323 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\node\Entity\Node;
+use Drupal\node\NodeInterface;
+
+/**
+ * Tests the IEF simple widget.
+ *
+ * @group inline_entity_form
+ */
+class SimpleWidgetTest extends InlineEntityFormTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['inline_entity_form_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'create ief_simple_single content',
+      'create ief_test_custom content',
+      'edit any ief_simple_single content',
+      'edit own ief_test_custom content',
+      'view own unpublished content',
+      'create ief_simple_entity_no_bundle content',
+      'administer entity_test__without_bundle content',
+    ]);
+  }
+
+  /**
+   * Tests simple IEF widget with different cardinality options.
+   */
+  public function testSimpleCardinalityOptions() {
+    // Get the xpath selectors for the fields in this test.
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $first_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $second_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 3);
+    $third_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 4);
+    $fourth_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 5);
+    $first_positive_int_field_xpath = $this->getXpathForNthInputByLabelText('Positive int', 1);
+    $second_positive_int_field_xpath = $this->getXpathForNthInputByLabelText('Positive int', 2);
+    $third_positive_int_field_xpath = $this->getXpathForNthInputByLabelText('Positive int', 3);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $this->drupalLogin($this->user);
+    $cardinality_options = [
+      1 => 1,
+      2 => 2,
+      FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED => 3,
+    ];
+    /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
+    $field_storage = $this->fieldStorageConfigStorage->load('node.single');
+
+    foreach ($cardinality_options as $cardinality => $number_of_items) {
+      $field_storage->setCardinality($cardinality);
+      $field_storage->save();
+
+      $this->drupalGet('node/add/ief_simple_single');
+
+      $assert_session->elementTextContains('css', 'span.fieldset-legend', 'Single node');
+      $assert_session->elementTextContains('css', 'div.description', 'Reference a single node.');
+
+      if ($cardinality === 1) {
+        // With cardinality 1, one item should already be on the page.
+        $assert_session->buttonNotExists('Add another item');
+        $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Host node');
+        $assert_session->elementExists('xpath', $first_nested_title_field_xpath)->setValue('Nested single node');
+        $assert_session->elementExists('xpath', $first_positive_int_field_xpath)->setValue(42);
+        $page->pressButton('Save');
+        $assert_session->pageTextContains('IEF single simple Host node has been created.');
+        $host_node = $this->getNodeByTitle('Host node');
+      }
+      elseif ($cardinality === 2) {
+        // With cardinality 2, two items should already be on the page.
+        $assert_session->buttonNotExists('Add another item');
+        $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Host node 2');
+        $assert_session->elementExists('xpath', $first_nested_title_field_xpath)->setValue('Nested single node 2');
+        $assert_session->elementExists('xpath', $first_positive_int_field_xpath)->setValue(42);
+        $assert_session->elementExists('xpath', $second_nested_title_field_xpath)->setValue('Nested single node 3');
+        $assert_session->elementExists('xpath', $second_positive_int_field_xpath)->setValue(42);
+        $page->pressButton('Save');
+        $assert_session->pageTextContains('IEF single simple Host node 2 has been created.');
+        $host_node = $this->getNodeByTitle('Host node 2');
+      }
+      elseif ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
+        // With unlimited cardinality, one item should already be on the page,
+        // and an 'Add another item' button should appear.
+        $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Host node 3');
+        $assert_session->elementExists('xpath', $first_nested_title_field_xpath)->setValue('Nested single node 4');
+        $assert_session->elementExists('xpath', $first_positive_int_field_xpath)->setValue(42);
+        $assert_session->elementNotExists('xpath', $second_positive_int_field_xpath);
+
+        // Press the 'add another item' button and add a second item.
+        $assert_session->buttonExists('Add another item')->press();
+        $this->assertNotEmpty($assert_session->waitForElement('xpath', $second_nested_title_field_xpath));
+        // Assert an extra item isn't added at the same time.
+        $assert_session->elementNotExists('xpath', $third_nested_title_field_xpath);
+        $assert_session->elementExists('xpath', $second_nested_title_field_xpath)->setValue('Nested single node 5');
+        $assert_session->elementExists('xpath', $second_positive_int_field_xpath)->setValue(42);
+
+        // Press the 'add another item' button and add a third item.
+        $assert_session->buttonExists('Add another item')->press();
+        $this->assertNotEmpty($assert_session->waitForElement('xpath', $third_nested_title_field_xpath));
+        // Assert an extra item isn't added at the same time.
+        $assert_session->elementNotExists('xpath', $fourth_nested_title_field_xpath);
+        $assert_session->elementExists('xpath', $third_nested_title_field_xpath)->setValue('Nested single node 6');
+        $assert_session->elementExists('xpath', $third_positive_int_field_xpath)->setValue(42);
+        $page->pressButton('Save');
+        $assert_session->pageTextContains('IEF single simple Host node 3 has been created.');
+        $host_node = $this->getNodeByTitle('Host node 3');
+      }
+      $this->checkEditAccess($host_node, $number_of_items, $cardinality);
+    }
+  }
+
+  /**
+   * Test Validation on Simple Widget.
+   */
+  public function testSimpleValidation() {
+    // Get the xpath selectors for the fields in this test.
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $positive_int_field_xpath = $this->getXpathForNthInputByLabelText('Positive int', 1);
+
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    $this->drupalLogin($this->user);
+    $host_node_title = 'Host Validation Node';
+    $this->drupalGet('node/add/ief_simple_single');
+
+    // Assert inline entity field widget title found.
+    $assert_session->pageTextContains('Single node');
+    // Assert inline entity field description found.
+    $assert_session->pageTextContains('Reference a single node.');
+    // Assert positive int field found.
+    $assert_session->pageTextContains('Positive int');
+
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue($host_node_title);
+    $page->pressButton('Save');
+
+    // Assert title validation fires on Inline Entity Form widget.
+    $assert_session->pageTextNotContains('IEF single simple Host Validation Node has been created.');
+    // Assert that we're still on form due to to validation error.
+    $this->assertSession()->addressEquals('node/add/ief_simple_single');
+
+    $child_title = 'Child node ' . $this->randomString();
+    $assert_session->elementExists('xpath', $nested_title_field_xpath)->setValue($child_title);
+    $assert_session->elementExists('xpath', $positive_int_field_xpath)->setValue(-1);
+    $page->pressButton('Save');
+    // Assert field validation fires on Inline Entity Form widget.
+    $assert_session->pageTextNotContains('IEF single simple Host Validation Node has been created.');
+    // Assert that we're still on form due to to validation error.
+    $this->assertSession()->addressEquals('node/add/ief_simple_single');
+
+    $assert_session->elementExists('xpath', $positive_int_field_xpath)->setValue(1);
+    $page->pressButton('Save');
+    // Assert title validation passes on Inline Entity Form widget.
+    $assert_session->pageTextNotContains('Title field is required.');
+    // Assert field validation fires on Inline Entity Form widget.
+    $assert_session->pageTextNotContains('Positive int must be higher than or equal to 1');
+    $assert_session->pageTextContains('IEF single simple Host Validation Node has been created.');
+
+    // Check that nodes were created correctly.
+    $host_node = $this->getNodeByTitle($host_node_title);
+    $this->assertNotNull($host_node, 'Host node created.');
+    if (isset($host_node)) {
+      // Assert that address is the canonical page after node add.
+      $this->assertSession()
+        ->addressEquals($host_node->toUrl('canonical', ['absolute' => TRUE])
+          ->toString());
+      $child_node = $this->getNodeByTitle($child_title);
+      $this->assertNotNull($child_node);
+      if (isset($child_node)) {
+        $this->assertSame($host_node->single[0]->target_id, $child_node->id(), 'Child node is referenced');
+        $this->assertSame($child_node->positive_int[0]->value, '1', 'Child node int field correct.');
+        $this->assertSame($child_node->bundle(), 'ief_test_custom', 'Child node is correct bundle.');
+      }
+    }
+  }
+
+  /**
+   * Tests if the entity create access works in the simple widget.
+   */
+  public function testSimpleCreateAccess() {
+    // Get the xpath selectors for the fields in this test.
+    $nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+
+    $assert_session = $this->assertSession();
+    // Create a user who does not have access to create ief_test_custom nodes.
+    $this->drupalLogin($this->createUser([
+      'create ief_simple_single content',
+    ]));
+    $this->drupalGet('node/add/ief_simple_single');
+    $assert_session->elementNotExists('xpath', $nested_title_field_xpath);
+    // Now test with a user has access to create ief_test_custom nodes.
+    $this->drupalLogin($this->user);
+    $this->drupalGet('node/add/ief_simple_single');
+    $assert_session->elementExists('xpath', $nested_title_field_xpath);
+  }
+
+  /**
+   * Ensures that an entity without bundles can be used with the simple widget.
+   */
+  public function testEntityWithoutBundle() {
+    // Get the xpath selectors for the fields in this test.
+    $title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 1);
+    $name_field_xpath = $this->getXpathForNthInputByLabelText('Name', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    $this->drupalLogin($this->user);
+    $this->drupalGet('node/add/ief_simple_entity_no_bundle');
+    $assert_session->elementExists('xpath', $title_field_xpath)->setValue('Node title');
+    $assert_session->elementExists('xpath', $name_field_xpath)->setValue('Entity title');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF simple entity no bundle Node title has been created.');
+    $this->assertNodeByTitle('Node title', 'ief_simple_entity_no_bundle');
+    $this->assertEntityByLabel('Entity title', 'entity_test__without_bundle');
+  }
+
+  /**
+   * Tests that user only has access to the their own nodes.
+   *
+   * @param \Drupal\node\NodeInterface $host_node
+   *   The node of the type of ief_simple_single.
+   * @param int $number_of_items
+   *   The number of entity reference values in the "single" field.
+   * @param int $cardinality
+   *   The field cardinality with which to check.
+   */
+  protected function checkEditAccess(NodeInterface $host_node, $number_of_items, $cardinality) {
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    $other_user = $this->createUser([
+      'edit own ief_test_custom content',
+      'edit any ief_simple_single content',
+    ]);
+    $first_child_node = $host_node->single[0]->entity;
+    $first_child_node->setOwner($other_user)->save();
+    $this->drupalGet("node/{$host_node->id()}/edit");
+    $assert_session->pageTextContains($first_child_node->label());
+    // Assert the form of child node without edit access is not found.
+    $assert_session->fieldNotExists('single[0][inline_entity_form][title][0][value]');
+    // Check that the forms for other child nodes (if any) appear on the form.
+    // If $number_of_items is greater than one, iterate through the other
+    // fields that should appear on the page.
+    $delta = 1;
+    while ($delta < $number_of_items) {
+      $child_node = $host_node->single[$delta]->entity;
+      // Assert the form of child node with edit access is found.
+      $delta_field = $assert_session->fieldExists("single[$delta][inline_entity_form][title][0][value]");
+      $this->assertContains($child_node->label(), $delta_field->getValue());
+      $delta++;
+    }
+    // Check that there is NOT an extra "add" form when editing.
+    $unexpected_item_number = $number_of_items;
+    // Assert no empty "add" entity form is found on edit.
+    $assert_session->fieldNotExists("single[$unexpected_item_number][inline_entity_form][title][0][value]");
+    if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
+      $next_item_number = $number_of_items;
+      $page->pressButton('Add another item');
+      // Assert item $next_item_number does appear after 'Add More'
+      // clicked.
+      $this->assertNotEmpty($assert_session->waitForField("single[$next_item_number][inline_entity_form][title][0][value]"));
+      // Make sure only 1 item is added.
+      $unexpected_item_number = $next_item_number + 1;
+      // Assert extra item $unexpected_item_number is not added after
+      // 'Add More' clicked.
+      $assert_session->fieldNotExists("single[$unexpected_item_number][inline_entity_form][title][0][value]");
+    }
+
+    // Now that we have confirmed the correct fields appear, let's update the
+    // values and save them. We do not have access to the form for delta 0
+    // because it is owned by another user.
+    $delta = 1;
+    $new_titles = [];
+    $edit = [];
+    // Loop through an update all child node titles.
+    while ($delta < $number_of_items) {
+      /** @var \Drupal\node\Entity\Node $child_node */
+      $child_node = $host_node->single[$delta]->entity;
+      $new_titles[$delta] = $child_node->label() . ' - updated';
+      $edit["single[$delta][inline_entity_form][title][0][value]"] = $new_titles[$delta];
+      $delta++;
+    }
+    // If cardinality equals CARDINALITY_UNLIMITED then we should have 1 extra
+    // form open.
+    if ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
+      $new_titles[$delta] = 'Title for new child';
+      $edit["single[$delta][inline_entity_form][title][0][value]"] = $new_titles[$delta];
+    }
+    $this->drupalPostForm(NULL, $edit, t('Save'));
+    $assert_session->pageTextContains("IEF single simple {$host_node->label()} has been updated.");
+
+    // Reset cache for nodes.
+    $node_ids = [$host_node->id()];
+    foreach ($host_node->single as $item) {
+      $node_ids[] = $item->entity->id();
+    }
+    $this->container
+      ->get('entity_type.manager')
+      ->getStorage('node')
+      ->resetCache($node_ids);
+    $host_node = Node::load($host_node->id());
+    // Check that titles were updated.
+    foreach ($new_titles as $delta => $new_title) {
+      $child_node = $host_node->single[$delta]->entity;
+      $this->assertSame($new_title, $child_node->label(), "Child $delta node title has been updated.");
+    }
+  }
+
+}
diff --git a/web/modules/inline_entity_form/tests/src/FunctionalJavascript/TranslationTest.php b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/TranslationTest.php
new file mode 100644
index 0000000000..ef798794ea
--- /dev/null
+++ b/web/modules/inline_entity_form/tests/src/FunctionalJavascript/TranslationTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace Drupal\Tests\inline_entity_form\FunctionalJavascript;
+
+use Drupal\node\Entity\Node;
+
+/**
+ * Tests translating inline entities.
+ *
+ * @group inline_entity_form
+ */
+class TranslationTest extends InlineEntityFormTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'content_translation',
+    'inline_entity_form_translation_test',
+    'language',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'create ief_reference_type content',
+      'edit any ief_reference_type content',
+      'delete any ief_reference_type content',
+      'create ief_test_complex content',
+      'edit any ief_test_complex content',
+      'delete any ief_test_complex content',
+      'view own unpublished content',
+      'administer content translation',
+      'translate any entity',
+      'create content translations',
+      'administer languages',
+    ]);
+    $this->drupalLogin($this->user);
+
+    // Allow referencing existing entities.
+    $form_display_storage = $this->container->get('entity_type.manager')->getStorage('entity_form_display');
+    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */
+    $display = $form_display_storage->load('node.ief_test_complex.default');
+    $component = $display->getComponent('multi');
+    $component['settings']['allow_existing'] = TRUE;
+    $display->setComponent('multi', $component)->save();
+  }
+
+  /**
+   * Tests translating inline entities.
+   */
+  public function testTranslation() {
+    // Get the xpath selectors for the fields in this test.
+    $first_nested_title_field_xpath = $this->getXpathForNthInputByLabelText('Title', 2);
+    $first_name_field_xpath = $this->getXpathForNthInputByLabelText('First name', 1);
+    $last_name_field_xpath = $this->getXpathForNthInputByLabelText('Last name', 1);
+
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+    // Create a German node with a French translation.
+    $first_inline_node = Node::create([
+      'type' => 'ief_reference_type',
+      'langcode' => 'de',
+      'title' => 'Kann ein Känguru höher als ein Haus springen?',
+      'first_name' => 'Dieter',
+    ]);
+    $translation = $first_inline_node->toArray();
+    $translation['title'][0]['value'] = "Un kangourou peut-il sauter plus haut qu'une maison?";
+    $translation['first_name'][0]['value'] = 'Pierre';
+    $first_inline_node->addTranslation('fr', $translation);
+    $first_inline_node->save();
+
+    $this->drupalGet('node/add/ief_test_complex');
+    $multi_fieldset = $assert_session->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $multi_fieldset->pressButton('Add existing node');
+    // Reference the German node.
+    $this->assertNotEmpty($field = $assert_session->waitForElement('xpath', $this->getXpathForAutoCompleteInput()));
+    $field->setValue('Kann ein Känguru höher als ein Haus springen? (' . $first_inline_node->id() . ')');
+    $page->pressButton('Add node');
+    $this->waitForRowByTitle('Kann ein Känguru höher als ein Haus springen?');
+
+    // Add a new English inline node.
+    $multi_fieldset->pressButton('Add new node');
+    $this->assertNotEmpty($create_button = $assert_session->waitForButton('Create node'));
+    $assert_session->elementExists('xpath', $first_nested_title_field_xpath)->setValue('Can a kangaroo jump higher than a house?');
+    $assert_session->elementExists('xpath', $first_name_field_xpath)->setValue('John');
+    $assert_session->elementExists('xpath', $last_name_field_xpath)->setValue('Smith');
+    $create_button->press();
+    $this->waitForRowByTitle('Can a kangaroo jump higher than a house?');
+    $this->assertRowByTitle('Kann ein Känguru höher als ein Haus springen?');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 2);
+    $page->fillField('title[0][value]', 'A node');
+    $page->selectFieldOption('langcode[0][value]', 'en');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('IEF test complex A node has been created.');
+
+    // Both inline nodes should now be in English.
+    $first_inline_node = $this->drupalGetNodeByTitle('Kann ein Känguru höher als ein Haus springen?');
+    $second_inline_node = $this->drupalGetNodeByTitle('Can a kangaroo jump higher than a house?');
+    $this->assertSame('en', $first_inline_node->get('langcode')->value, 'The first inline entity has the correct langcode.');
+    $this->assertEqual('en', $second_inline_node->get('langcode')->value, 'The second inline entity has the correct langcode.');
+
+    // Edit the parent node and change the source language to German.
+    $node = $this->drupalGetNodeByTitle('A node');
+    $this->drupalGet('node/' . $node->id() . '/edit');
+    $page->selectFieldOption('langcode[0][value]', 'de');
+    $page->pressButton('Save');
+
+    // Both inline nodes should now be in German.
+    $first_inline_node = $this->drupalGetNodeByTitle('Kann ein Känguru höher als ein Haus springen?', TRUE);
+    $second_inline_node = $this->drupalGetNodeByTitle('Can a kangaroo jump higher than a house?', TRUE);
+    $this->assertSame('de', $first_inline_node->get('langcode')->value, 'The first inline entity has the correct langcode.');
+    $this->assertSame('de', $second_inline_node->get('langcode')->value, 'The second inline entity has the correct langcode.');
+
+    // Add a German -> French translation of the parent node.
+    $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr');
+
+    $assert_session->elementTextContains('xpath', '//fieldset[@id="edit-multi"]/legend/span', 'Multiple nodes');
+
+    // Confirm that the add and remove buttons are not present.
+    $multi_fieldset = $assert_session->elementExists('css', 'fieldset[data-drupal-selector="edit-multi"]');
+    $this->assertEquals(FALSE, $multi_fieldset->hasButton('Add new node'));
+    $this->assertEquals(FALSE, $multi_fieldset->hasButton('Remove'));
+
+    // Confirm the presence of the two node titles, in the expected languages.
+    $first_reference = $this->assertRowByTitle("Un kangourou peut-il sauter plus haut qu'une maison?");
+    $second_reference = $this->assertRowByTitle('Can a kangaroo jump higher than a house?');
+    $assert_session->elementsCount('css', 'tr.ief-row-entity', 2);
+
+    // Edit the first referenced translation.
+    $first_reference->getParent()->pressButton('Edit');
+    $this->assertNotEmpty($update_button = $assert_session->waitForButton('Update node'));
+    $assert_session->elementExists('xpath', $first_nested_title_field_xpath)->setValue("Un kangourou peut-il sauter plus haut qu'une maison? - mis à jour");
+    $assert_session->elementExists('xpath', $first_name_field_xpath)->setValue('Damien');
+    $update_button->press();
+    $this->waitForRowByTitle("Un kangourou peut-il sauter plus haut qu'une maison? - mis à jour");
+    // Edit the second referenced translation.
+    $second_reference->getParent()->pressButton('Edit');
+    $this->assertNotEmpty($update_button = $assert_session->waitForButton('Update node'));
+    $assert_session->elementExists('xpath', $first_nested_title_field_xpath)->setValue('tous les animaux qui sautent');
+    $assert_session->elementExists('xpath', $first_name_field_xpath)->setValue('Jacques');
+    $update_button->press();
+    $this->waitForRowByTitle('tous les animaux qui sautent');
+    $page->pressButton('Save (this translation)');
+    $assert_session->pageTextContains('IEF test complex A node has been updated.');
+
+    // Load using the original titles, confirming they haven't changed.
+    $first_inline_node = $this->drupalGetNodeByTitle('Kann ein Känguru höher als ein Haus springen?', TRUE);
+    $second_inline_node = $this->drupalGetNodeByTitle('Can a kangaroo jump higher than a house?', TRUE);
+    // Confirm that the expected translated values are present.
+    $this->assertEquals(TRUE, $first_inline_node->hasTranslation('fr'), 'The first inline entity has a FR translation');
+    $this->assertEquals(TRUE, $second_inline_node->hasTranslation('fr'), 'The second inline entity has a FR translation');
+    $first_translation = $first_inline_node->getTranslation('fr');
+    $this->assertSame("Un kangourou peut-il sauter plus haut qu'une maison? - mis à jour", $first_translation->title->value);
+    $this->assertSame('Damien', $first_translation->first_name->value);
+    $second_translation = $second_inline_node->getTranslation('fr');
+    $this->assertEquals('tous les animaux qui sautent', $second_translation->title->value);
+    $this->assertSame('Jacques', $second_translation->first_name->value);
+  }
+
+}
-- 
GitLab