 .../edit/Access/EditEntityFieldAccessCheck.php     |    3 +-
 .../edit/lib/Drupal/edit/MetadataGenerator.php     |    3 +-
 .../edit/lib/Drupal/edit/Tests/EditTestBase.php    |   93 +++++++++++++++
 .../lib/Drupal/edit/Tests/EditorSelectionTest.php  |   78 +-----------
 .../Drupal/edit/Tests/MetadataGeneratorTest.php    |  124 ++++++++++++++++++++
 .../edit_test/MockEditEntityFieldAccessCheck.php   |   27 +++++
 6 files changed, 250 insertions(+), 78 deletions(-)

diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
index 82726c3..9eac5bc 100644
--- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
+++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
@@ -42,7 +42,8 @@ public function access(Route $route, Request $request) {
    */
   public function accessEditEntityField(EntityInterface $entity, $field_name) {
     $entity_type = $entity->entityType();
-    // @todo Generalize to all entity types: http://drupal.org/node/1839516.
+    // @todo Generalize to all entity types once http://drupal.org/node/1862750
+    // is done.
     return ($entity_type == 'node' && node_access('update', $entity) && field_access('edit', $field_name, $entity_type, $entity));
   }
 
diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
index bdbdf10..cd3849a 100644
--- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
+++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\field\FieldInstance;
+use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
 
 use Drupal\edit\Access\EditEntityFieldAccessCheckInterface;
 
@@ -58,7 +59,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
     }
 
     $label = $instance['label'];
-    $formatter_id = $instance->getFormatter($view_mode)->getPluginId();
+    $formatter_id = entity_get_render_display($entity, $view_mode)->getFormatter($instance['field_name'])->getPluginId();
     $items = $entity->get($field_name);
     $items = $items[$langcode];
     $editor = $this->editorSelector->getEditor($formatter_id, $instance, $items);
diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
new file mode 100644
index 0000000..573ce93
--- /dev/null
+++ b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\edit\Tests\EditTestBase.
+ */
+
+namespace Drupal\edit\Tests;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Parent class for Edit tests.
+ */
+class EditTestBase extends DrupalUnitTestBase {
+  var $default_storage = 'field_sql_storage';
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('system', 'entity', 'field_test', 'field', 'number', 'text', 'edit', 'edit_test');
+
+  /**
+   * Sets the default field storage backend for fields created during tests.
+   */
+  function setUp() {
+    parent::setUp();
+
+    $this->installSchema('system', 'variable');
+    $this->enableModules(array('field', 'field_sql_storage', 'field_test'));
+
+    // Set default storage backend.
+    variable_set('field_storage_default', $this->default_storage);
+  }
+
+  /**
+   * Creates a field and an instance of it.
+   *
+   * @param string $field_name
+   *   The field name.
+   * @param string $type
+   *   The field type.
+   * @param int $cardinality
+   *   The field's cardinality.
+   * @param string $label
+   *   The field's label (used everywhere: widget label, formatter label).
+   * @param array $instance_settings
+   * @param string $widget_type
+   *   The widget type.
+   * @param array $widget_settings
+   *   The widget settings.
+   * @param string $formatter_type
+   *   The formatter type.
+   * @param array $formatter_settings
+   *   The formatter settings.
+   */
+  function createFieldWithInstance($field_name, $type, $cardinality, $label, $instance_settings, $widget_type, $widget_settings, $formatter_type, $formatter_settings) {
+    $field = $field_name . '_field';
+    $this->$field = array(
+      'field_name' => $field_name,
+      'type' => $type,
+      'cardinality' => $cardinality,
+    );
+    $this->$field_name = field_create_field($this->$field);
+
+    $instance = $field_name . '_instance';
+    $this->$instance = array(
+      'field_name' => $field_name,
+      'entity_type' => 'test_entity',
+      'bundle' => 'test_bundle',
+      'label' => $label,
+      'description' => $label,
+      'weight' => mt_rand(0, 127),
+      'settings' => $instance_settings,
+      'widget' => array(
+        'type' => $widget_type,
+        'label' => $label,
+        'settings' => $widget_settings,
+      ),
+    );
+    field_create_instance($this->$instance);
+
+    entity_get_display('test_entity', 'test_bundle', 'default')
+      ->setComponent($field_name, array(
+        'label' => 'above',
+        'type' => $formatter_type,
+        'settings' => $formatter_settings
+      ))
+      ->save();
+  }
+}
diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php b/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php
index db26798..5217b92 100644
--- a/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php
+++ b/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php
@@ -7,15 +7,13 @@
 
 namespace Drupal\edit\Tests;
 
-use Drupal\simpletest\DrupalUnitTestBase;
 use Drupal\edit\Plugin\ProcessedTextEditorManager;
 use Drupal\edit\EditorSelector;
 
 /**
  * Test in-place field editor selection.
  */
-class EditorSelectionTest extends DrupalUnitTestBase {
-  var $default_storage = 'field_sql_storage';
+class EditorSelectionTest extends EditTestBase {
 
   /**
    * The editor selector object to be tested.
@@ -24,13 +22,6 @@ class EditorSelectionTest extends DrupalUnitTestBase {
    */
   protected $editorSelector;
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('system', 'entity', 'field_test', 'field', 'number', 'text', 'edit', 'edit_test');
-
   public static function getInfo() {
     return array(
       'name' => 'In-place field editor selection',
@@ -39,18 +30,9 @@ public static function getInfo() {
     );
   }
 
-  /**
-   * Sets the default field storage backend for fields created during tests.
-   */
   function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'variable');
-    $this->enableModules(array('field', 'field_sql_storage', 'field_test'));
-
-    // Set default storage backend.
-    variable_set('field_storage_default', $this->default_storage);
-
     // @todo Rather than using the real ProcessedTextEditorManager, which can
     //   find all text editor plugins in the codebase, create a mock one for
     //   testing that is populated with only the ones we want to test.
@@ -60,66 +42,10 @@ function setUp() {
   }
 
   /**
-   * Creates a field and an instance of it.
-   *
-   * @param string $field_name
-   *   The field name.
-   * @param string $type
-   *   The field type.
-   * @param int $cardinality
-   *   The field's cardinality.
-   * @param string $label
-   *   The field's label (used everywhere: widget label, formatter label).
-   * @param array $instance_settings
-   * @param string $widget_type
-   *   The widget type.
-   * @param array $widget_settings
-   *   The widget settings.
-   * @param string $formatter_type
-   *   The formatter type.
-   * @param array $formatter_settings
-   *   The formatter settings.
-   */
-  function createFieldWithInstance($field_name, $type, $cardinality, $label, $instance_settings, $widget_type, $widget_settings, $formatter_type, $formatter_settings) {
-    $field = $field_name . '_field';
-    $this->$field = array(
-      'field_name' => $field_name,
-      'type' => $type,
-      'cardinality' => $cardinality,
-    );
-    $this->$field_name = field_create_field($this->$field);
-
-    $instance = $field_name . '_instance';
-    $this->$instance = array(
-      'field_name' => $field_name,
-      'entity_type' => 'test_entity',
-      'bundle' => 'test_bundle',
-      'label' => $label,
-      'description' => $label,
-      'weight' => mt_rand(0, 127),
-      'settings' => $instance_settings,
-      'widget' => array(
-        'type' => $widget_type,
-        'label' => $label,
-        'settings' => $widget_settings,
-      ),
-    );
-    field_create_instance($this->$instance);
-
-    entity_get_display('test_entity', 'test_bundle', 'default')
-      ->setComponent($field_name, array(
-        'label' => 'above',
-        'type' => $formatter_type,
-        'settings' => $formatter_settings
-      ))
-      ->save();
-  }
-
-  /**
    * Retrieves the FieldInstance object for the given field and returns the
    * editor that Edit selects.
    */
-  function getSelectedEditor($items, $field_name, $view_mode = 'default') {
+  protected function getSelectedEditor($items, $field_name, $view_mode = 'default') {
     $options = entity_get_display('test_entity', 'test_bundle', $view_mode)->getComponent($field_name);
     $field_instance = field_info_instance('test_entity', $field_name, 'test_bundle');
     return $this->editorSelector->getEditor($options['type'], $field_instance, $items);
diff --git a/core/modules/edit/lib/Drupal/edit/Tests/MetadataGeneratorTest.php b/core/modules/edit/lib/Drupal/edit/Tests/MetadataGeneratorTest.php
new file mode 100644
index 0000000..e8060ea
--- /dev/null
+++ b/core/modules/edit/lib/Drupal/edit/Tests/MetadataGeneratorTest.php
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\edit\Tests\MetadataGeneratorTest.
+ */
+
+namespace Drupal\edit\Tests;
+
+use Drupal\edit\EditorSelector;
+use Drupal\edit\MetadataGenerator;
+use Drupal\edit\Plugin\ProcessedTextEditorManager;
+use Drupal\edit_test\MockEditEntityFieldAccessCheck;
+
+/**
+ * Test in-place field editing metadata.
+ */
+class MetadataGeneratorTest extends EditTestBase {
+
+  /**
+   * The metadata generator object to be tested.
+   *
+   * @var \Drupal\edit\MetadataGeneratorInterface.php
+   */
+  protected $metadataGenerator;
+
+  /**
+   * The editor selector object to be used by the metadata generator object.
+   *
+   * @var \Drupal\edit\EditorSelectorInterface
+   */
+  protected $editorSelector;
+
+  /**
+   * The access checker object to be used by the metadata generator object.
+   *
+   * @var \Drupal\edit\Access\EditEntityFieldAccessCheckInterface
+   */
+  protected $accessChecker;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'In-place field editing metadata',
+      'description' => 'Tests in-place field editing metadata generation.',
+      'group' => 'Edit',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // @todo Rather than using the real ProcessedTextEditorManager, which can
+    //   find all text editor plugins in the codebase, create a mock one for
+    //   testing that is populated with only the ones we want to test.
+    $text_editor_manager = new ProcessedTextEditorManager();
+
+    $this->accessChecker = new MockEditEntityFieldAccessCheck();
+    $this->editorSelector = new EditorSelector($text_editor_manager);
+    $this->metadataGenerator = new MetadataGenerator($this->accessChecker, $this->editorSelector);
+  }
+
+  /**
+   * Tests a simple entity type, with two different simple fields.
+   */
+  function testSimpleEntityType() {
+    $field_1_name = 'field_text';
+    $field_1_label = 'Simple text field';
+    $this->createFieldWithInstance(
+      $field_1_name, 'text', 1, $field_1_label,
+      // Instance settings.
+      array('text_processing' => 0),
+      // Widget type & settings.
+      'text_textfield',
+      array('size' => 42),
+      // 'default' formatter type & settings.
+      'text_default',
+      array()
+    );
+    $field_2_name = 'field_nr';
+    $field_2_label = 'Simple number field';
+    $this->createFieldWithInstance(
+      $field_2_name, 'number_integer', 1, $field_2_label,
+      // Instance settings.
+      array(),
+      // Widget type & settings.
+      'number',
+      array(),
+      // 'default' formatter type & settings.
+      'number_integer',
+      array()
+    );
+
+    // Create an entity with values for this text field.
+    $this->entity = field_test_create_entity();
+    $this->is_new = TRUE;
+    $this->entity->{$field_1_name}[LANGUAGE_NOT_SPECIFIED] = array(array('value' => 'Test'));
+    $this->entity->{$field_2_name}[LANGUAGE_NOT_SPECIFIED] = array(array('value' => 42));
+    field_test_entity_save($this->entity);
+    $entity = entity_load('test_entity', $this->entity->ftid);
+
+    // Verify metadata for field 1.
+    $instance_1 = field_info_instance($entity->entityType(), $field_1_name, $entity->bundle());
+    $metadata_1 = $this->metadataGenerator->generate($entity, $instance_1, LANGUAGE_NOT_SPECIFIED, 'default');
+    $expected_1 = array(
+      'access' => TRUE,
+      'label' => 'Simple text field',
+      'editor' => 'direct',
+      'aria' => 'Entity test_entity 1, field Simple text field',
+    );
+    $this->assertEqual($expected_1, $metadata_1, 'The correct metadata is generated for the first field.');
+
+    // Verify metadata for field 2.
+    $instance_2 = field_info_instance($entity->entityType(), $field_2_name, $entity->bundle());
+    $metadata_2 = $this->metadataGenerator->generate($entity, $instance_2, LANGUAGE_NOT_SPECIFIED, 'default');
+    $expected_2 = array(
+      'access' => TRUE,
+      'label' => 'Simple number field',
+      'editor' => 'form',
+      'aria' => 'Entity test_entity 1, field Simple number field',
+    );
+    $this->assertEqual($expected_2, $metadata_2, 'The correct metadata is generated for the second field.');
+
+  }
+}
diff --git a/core/modules/edit/tests/modules/lib/Drupal/edit_test/MockEditEntityFieldAccessCheck.php b/core/modules/edit/tests/modules/lib/Drupal/edit_test/MockEditEntityFieldAccessCheck.php
new file mode 100644
index 0000000..9b67f9c
--- /dev/null
+++ b/core/modules/edit/tests/modules/lib/Drupal/edit_test/MockEditEntityFieldAccessCheck.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\edit_test\MockEditEntityFieldAccessCheck.
+ *
+ * @todo We may want to get rid of this once http://drupal.org/node/1862750 is done.
+ */
+
+namespace Drupal\edit_test;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\edit\Access\EditEntityFieldAccessCheckInterface;
+
+/**
+ * Access check for editing entity fields.
+ */
+class MockEditEntityFieldAccessCheck implements EditEntityFieldAccessCheckInterface {
+
+  /**
+   * Implements EntityFieldAccessCheckInterface::accessEditEntityField().
+   */
+  public function accessEditEntityField(EntityInterface $entity, $field_name) {
+    return TRUE;
+  }
+
+}
