diff --git a/tests/modules/scheduler_api_test.install b/tests/modules/scheduler_api_test.install
index b79348a..ebcc999 100644
--- a/tests/modules/scheduler_api_test.install
+++ b/tests/modules/scheduler_api_test.install
@@ -5,110 +5,23 @@
  * Install and uninstall hooks for the Scheduler API Test module.
  */
 
-use Drupal\field\Entity\FieldConfig;
-use Drupal\node\Entity\NodeType; // needed for NodeType::loadMultiple();
-use Drupal\node\NodeTypeInterface;
-use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\Core\Field\BaseFieldDefinition;
-
 /**
  * Implements hook_install().
  */
 function scheduler_api_test_install() {
-//   dd('==scheduler_api_test_install()==');
-  // Ensure the scheduler_api_test node type is available.
-  $types = NodeType::loadMultiple();
-  if (!isset($types['scheduler_api_test'])) {
-    // Create the node type.
-    $node_type = entity_create('node_type', ['type' => 'scheduler_api_test', 'name' => 'Scheduler API testing', 'description' => 'Simulated third-party module used for testing Scheduler API and hook function']);
-    $node_type->save();
-    // Attach a body field to the node type.
-    node_add_body_field($node_type);
-  }
-
-  $node_names = node_type_get_names();
-//   dd($node_names, '$node_names'); // for debug;
-
-  $field_name = 'approved';
-  $field = FieldStorageConfig::loadByName('node', $field_name);
-//   dd(empty($field) ? 'empty' : $field, 'field named ' . $field_name);
-
-  $entity_manager = \Drupal::entityManager();
-  $definitions = $entity_manager->getFieldStorageDefinitions('node');
-  $definition_names = array_keys($definitions);
-//   dd($definition_names, 'definition_names');
-
-  // Create field storage for the 'approved' base field.
-  if (isset($definitions[$field_name])) {
-//     dd($definitions[$field_name], "definitions[$field_name]");
-  }
-  else {
-//     dd("No definition for '$field_name'. Now creating ...");
-
-   // block_content.install has code just like this. What is different such that it works there? Maybe the field already exists?
-    $field_definition = BaseFieldDefinition::create('integer')
-      ->setLabel(ucfirst($field_name))
-      ->setDescription(t('Approved for publication'));
-//     dd($field_definition, '$field_definition'); // all ok.
-
-//    \Drupal::entityManager()->clearCachedDefinitions();
-//   $entity_manager->onFieldStorageDefinitionCreate($field_definition); // gives message: the '' entity type does not exist
-
-    $ins = ($field_definition instanceof BaseFieldDefinition);
-//     dd($ins, '$field_definition is instanceof BaseFieldDefinition?');
-
-    \Drupal::entityDefinitionUpdateManager()
-      ->installFieldStorageDefinition($field_name, 'node', 'scheduler_api_test', $field_definition);
-
-//    \Drupal::service('entity.definition_update_manager')->applyUpdates(); // removes 'Mismatched entity and/or field definitions The following changes were detected in the entity type and field definitions. Content Delete the APP3 + app3 field.' from status report
-  }
 }
 
 /**
- * Implements hook_install().
- * This is the original 7.x version left here temporarily for reference.
+ * Implements hook_uninstall().
  */
-function scheduler_test_7xinstall() {
-
-  $t = get_t();
-
-  // Ensure the scheduler_test node type is available.
-  node_types_rebuild();
-  $types = node_type_get_types();
-
-  // Attach a body field to the node type.
-  node_add_body_field($types['scheduler_test']);
-
-  // Create a field to attach to the node type.
-  $field = field_info_field('field_scheduler_test_approved');
-  if (empty($field)) {
-    $field = array(
-      'field_name' => 'field_scheduler_test_approved',
-      'type' => 'list_integer',
-      'entity_types' => array('node'),
-      'cardinality' => 2,
-      'settings' => array(
-        'allowed_values' => array(
-          1 => $t('Approved for publication by the CEO'),
-        ),
-      ),
-    );
-    $field = field_create_field($field);
-  }
-
-  $instance = field_info_instance('node', 'field_scheduler_test_approved', 'scheduler_test');
-  if (empty($instance)) {
-    $instance = array(
-      'bundle' => 'scheduler_test',
-      'display' => array(
-        'default' => array('type' => 'list_default'),
-        'teaser' => array('type' => 'hidden'),
-      ),
-      'entity_type' => 'node',
-      'field_name' => 'field_scheduler_test_approved',
-      'label' => 'Approved',
-      'widget' => array('type' => 'options_buttons'),
-    );
-    field_create_instance($instance);
-  }
+function scheduler_api_test_uninstall() {
+  // Delete the custom node type and other config items.
+  \Drupal::configFactory()->getEditable('node.type.scheduler_api_test')->delete();
+  \Drupal::configFactory()->getEditable('field.storage.node.field_approved')->delete();
+  \Drupal::configFactory()->getEditable('field.field.node.scheduler_api_test.field_approved')->delete();
+  \Drupal::configFactory()->getEditable('core.entity_form_display.node.scheduler_api_test.default')->delete();
+  \Drupal::configFactory()->getEditable('core.entity_view_display.node.scheduler_api_test.default')->delete();
+  ### @todo Shouldn't this be automatic on uninstall?
+  ### After manual uninstall the node type is still available.
+  ### Cannot re-install until these are removed.
 }
diff --git a/tests/modules/scheduler_api_test.module b/tests/modules/scheduler_api_test.module
index e10c4b2..1bada35 100644
--- a/tests/modules/scheduler_api_test.module
+++ b/tests/modules/scheduler_api_test.module
@@ -2,38 +2,24 @@
 
 /**
  * @file
- * Main functions and hook implementations of the Scheduler Test module.
+ * Hook implementations of the Scheduler API Test module.
  */
 
 /**
- * Implements hook_node_info().
- */
-function scheduler_test_node_info() {
-  $items = array(
-    'scheduler_test' => array(
-      'name' => t('Scheduler test'),
-      'base' => 'node_content',
-      'description' => t('This content type is used to test the Scheduler module.'),
-      'has_title' => '1',
-      'title_label' => t('Title'),
-    ),
-  );
-  return $items;
-}
-
-/**
  * Implements hook_scheduler_allow_publishing().
  */
-function scheduler_test_scheduler_allow_publishing($node) {
-  // Only publish nodes that have the 'Approved for publication by the CEO'
-  // checkbox ticked.
-  $items = $node->field_scheduler_test_approved->getValue();
-  $allowed = !empty($items[0]['value']);
-
-  // If publication is denied then inform the user why.
-  if (!$allowed) {
-    drupal_set_message(t('The content will only be published after approval by the CEO.'), 'status', FALSE);
+function scheduler_api_test_scheduler_allow_publishing($node) {
+  // If there is no 'approved' field do nothing to change the result.
+  if (!isset($node->field_approved)) {
+    $allowed = TRUE;
+  }
+  else {
+    // Only publish nodes that have the 'Approved' checkbox ticked.
+    $allowed = $node->field_approved->value;
+    // If publication is denied then inform the user why.
+    if (!$allowed) {
+      drupal_set_message(t('The content can be scheduled, but will only be published after approval by the CEO.'), 'status', FALSE);
+    }
   }
-
   return $allowed;
 }
diff --git a/tests/modules/config/install/node.type.scheduler_api_test.yml b/tests/modules/config/install/node.type.scheduler_api_test.yml
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/config/install/field.storage.node.field_approved.yml b/tests/modules/config/install/field.storage.node.field_approved.yml
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/config/install/field.field.node.scheduler_api_test.field_approved.yml b/tests/modules/config/install/field.field.node.scheduler_api_test.field_approved.yml
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/config/install/core.entity_form_display.node.scheduler_api_test.default.yml b/tests/modules/config/install/core.entity_form_display.node.scheduler_api_test.default.yml
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modules/config/install/core.entity_view_display.node.scheduler_api_test.default.yml b/tests/modules/config/install/core.entity_view_display.node.scheduler_api_test.default.yml
new file mode 100644
index 0000000..e69de29
diff --git a/src/Tests/SchedulerApiTestCase.php b/src/Tests/SchedulerApiTestCase.php
index d6492f4..416d370 100644
--- a/src/Tests/SchedulerApiTestCase.php
+++ b/src/Tests/SchedulerApiTestCase.php
@@ -7,9 +7,6 @@
 
 namespace Drupal\scheduler\Tests;
 
-use Drupal\Component\Utility\SafeMarkup;
-use Drupal\node\Entity\Node;
-use Drupal\simpletest\WebTestBase;
 use Drupal\node\Entity\NodeType;
 
 /**
@@ -22,38 +19,35 @@ class SchedulerApiTestCase extends SchedulerTestBase {
   /**
    * The additional modules to be loaded for this test.
    */
-  public static $modules = ['scheduler_api_test'];
+  public static $modules = ['scheduler_api_test', 'menu_ui', 'path'];
+  // @todo 'menu_ui' is in the exported node.type definition, and 'path' is in
+  // the entity_form_display. Could these be removed from the config files and
+  // then not needed here?
 
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  public function setUp() {
     parent::setUp();
-    $config = $this->config('scheduler.settings');
 
-    // TEMP. Add these lines to send devel dd() to the usual file.     
-    debug(file_directory_temp(), 'existing file_directory_temp()');   
-    \Drupal::configFactory()->getEditable('system.file')->set('path.temporary', '/private/tmp')->save(TRUE);   
-    debug(file_directory_temp(), 'new file_directory_temp()');   
-
-    // Add scheduler functionality to the custom node type.
-    $this->nodetype = NodeType::load('scheduler_api_test');
+    // Load the custom node type and check it .
+    $this->custom_type = 'scheduler_api_test';
+    $this->nodetype = NodeType::load($this->custom_type);
     if ($this->nodetype) {
-      $this->nodetype->setThirdPartySetting('scheduler', 'publish_enable', TRUE)
-        ->setThirdPartySetting('scheduler', 'unpublish_enable', TRUE)
-        ->save();
-      debug($this->nodetype->get('type'), 'nodetype->get(type)');
-      debug($this->nodetype->get('name'), 'nodetype->get(name)');
+      $this->pass('Custom node type ' . $this->custom_type . ' "' . $this->nodetype->get('name') . '"  created during install');
+      // Do not need to enable this node type for scheduler as that is already
+      // pre-configured in node.type.scheduler_api_test.yml
     }
     else {
-      $this->fail('Node type "scheduler_api_test" was not created');
+      $this->fail('*** Custom node type ' . $this->custom_type . ' does not exist. Testing abandoned ***');
       return;
     }
-    $node_type_names = node_type_get_names();
-    debug($node_type_names, '$node_type_names'); // for debug;
-    
-    // Create an administrator user.
-    $this->adminUser = $this->drupalCreateUser(['create ' . $this->nodetype->get('type') . ' content', 'edit any ' . $this->nodetype->get('type') . ' content',]);
+
+    // Create a web user for this content type.
+    $this->webUser = $this->drupalCreateUser([
+      'create ' . $this->custom_type . ' content',
+      'edit any ' . $this->custom_type . ' content',
+    ]);
 
     // Create node_storage property.
     $this->node_storage = $this->container->get('entity.manager')->getStorage('node');
@@ -71,43 +65,50 @@ class SchedulerApiTestCase extends SchedulerTestBase {
    *   the correct messages are displayed.
    */
   public function testAllowedPublishing() {
-    if (!NodeType::load('scheduler_api_test')) {
-      $this->fail('*** testing abandoned ***');
+    if (empty($this->nodetype)) {
+      $this->fail('*** Custom node type ' . $this->custom_type . ' does not exist. Testing abandoned ***');
       return;
     }
 
     // Check that the approved field is shown on the node/add form.
-    $this->drupalLogin($this->adminUser);
-    $this->drupalGet('node/add/' . $this->nodetype->get('type'));
-    $this->assertFieldByName('approved[0][value]', '', 'The Approved field is shown on the node form');
-    
+    $this->drupalLogin($this->webUser);
+    $this->drupalGet('node/add/' . $this->custom_type);
+    $this->assertFieldById('edit-field-approved-value', '', 'The Approved field is shown on the node form');
+
     // Create a node that is scheduled but not approved for publication. Then
-    // simulate a cron run, and check that the node is not published.
-    debug('scheduled unapproved node');
+    // simulate a cron run, and check that the node is still not published.
     $node = $this->createUnapprovedNode();
-    $this->drupalGet('node/' . $node->id() . '/edit'); // debug to display the node created.
     scheduler_cron();
     $this->node_storage->resetCache(array($node->id()));
     $node = $this->node_storage->load($node->id());
-    $this->assertFalse($node->isPublished(), 'An unapproved node is not published after scheduling.');
+    $this->assertFalse($node->isPublished(), 'An unapproved node is not published during cron processing.');
 
-    // Approve the node for publication, simulate a cron run, check that the
+    // Approve the node for publication, simulate a cron run and check that the
     // node is now published.
-    debug('now approving the node');
     $this->approveNode($node->id());
     scheduler_cron();
     $this->node_storage->resetCache(array($node->id()));
     $node = $this->node_storage->load($node->id());
-    $this->assertTrue($node->isPublished(), 'An approved node is published after scheduling.');
+    $this->assertTrue($node->isPublished(), 'An approved node is published during cron processing.');
 
     // Turn on immediate publication of nodes with publication dates in the past
-    // and repeat the tests. It is not needed to simulate cron runs now.
-    debug('turn on immediate publishing');
+    // and repeat the tests. It is not needed to simulate cron runs here.
     $this->nodetype->setThirdPartySetting('scheduler', 'publish_past_date', 'publish')->save();
     $node = $this->createUnapprovedNode();
-    $this->assertFalse($node->isPublished(), 'An unapproved node is not published immediately after saving.');
+    $this->assertFalse($node->isPublished(), 'An unapproved node with a date in the past is not published immediately after saving.');
+
+    // Check that the node can be approved and published programatically.
     $this->approveNode($node->id());
-    $this->assertTrue($node->isPublished(), 'An approved node is published immediately after saving.');
+    $this->node_storage->resetCache(array($node->id()));
+    $node = $this->node_storage->load($node->id());
+    $this->assertTrue($node->isPublished(), 'An approved node with a date in the past is published immediately via $node->set()->save().');
+
+    // Check that a node can be approved and published via edit form.
+    $node = $this->createUnapprovedNode();
+    $this->drupalPostForm('node/' . $node->id() . '/edit', ['field_approved[value]' => '1'], t('Save'));
+    $this->node_storage->resetCache(array($node->id()));
+    $node = $this->node_storage->load($node->id());
+    $this->assertTrue($node->isPublished(), 'An approved node with a date in the past is published immediately after saving via edit form.');
   }
 
   /**
@@ -123,7 +124,8 @@ class SchedulerApiTestCase extends SchedulerTestBase {
     $settings = array(
       'status' => 0,
       'publish_on' => strtotime('-1 day'),
-      'type' => $this->nodetype->get('type'),
+      'field_approved' => 0,
+      'type' => $this->custom_type,
     );
     return $this->drupalCreateNode($settings);
   }
@@ -132,14 +134,12 @@ class SchedulerApiTestCase extends SchedulerTestBase {
    * Approves a node for publication.
    *
    * @param int $nid
-   *   The nid of the node to approve.
+   *   The id of the node to approve.
    */
   protected function approveNode($nid) {
-    $node_storage = $this->container->get('entity.manager')->getStorage('node');
-    $node_storage->resetCache(array($nid));
-    $node = $node_storage->load($nid);
-    $node->set('field_scheduler_api_test_approved' , TRUE);
-    $node->save();
+    $this->node_storage->resetCache(array($nid));
+    $node = $this->node_storage->load($nid);
+    $node->set('field_approved' , TRUE)->save();
   }
 
 }
