diff --git a/includes/simplenews.mail.inc b/includes/simplenews.mail.inc
index 72fb227..47f9998 100644
--- a/includes/simplenews.mail.inc
+++ b/includes/simplenews.mail.inc
@@ -88,6 +88,7 @@ function simplenews_send_node($node, $accounts = array()) {
       simplenews_mail_spool($spool_data['nid'], $spool_data['vid'], 999999);
       drupal_set_message(t('Newsletter sent.'));
       simplenews_clear_spool();
+      simplenews_send_status_update();
     }
     else {
       drupal_set_message(t('Newsletter pending.'));
diff --git a/simplenews.install b/simplenews.install
index 2ff111d..1912536 100644
--- a/simplenews.install
+++ b/simplenews.install
@@ -116,7 +116,7 @@ function simplenews_schema() {
         'default' => 0,
       ),
       'status' => array(
-        'description' => 'sent status of the newsletter issue (0 = not sent; 1 = pending; 2 = sent). ',
+        'description' => 'sent status of the newsletter issue (0 = not sent; 1 = pending; 2 = sent, 3 = send on publish).',
         'type' => 'int',
         'size' => 'tiny',
         'not null' => TRUE,
diff --git a/simplenews.js b/simplenews.js
deleted file mode 100644
index 5ff42c4..0000000
--- a/simplenews.js
+++ /dev/null
@@ -1,28 +0,0 @@
-(function ($) {
-
-/**
- * Set text of Save button dependent on the selected send option.
- */
-Drupal.behaviors.simplenewsCommandSend = {
-  attach: function (context) {
-    var commandSend = $(".simplenews-command-send", context);
-    var sendButton = function () {
-      switch ($(":radio:checked", commandSend).val()) {
-      case '0':
-        $('#edit-submit', context).attr({value: Drupal.t('Send test')});
-        $('.form-item-simplenews-test-address', context).fadeIn();
-        break;
-      case '1':
-        $('#edit-submit', context).attr({value: Drupal.t('Save and send')});
-        $('.form-item-simplenews-test-address', context).slideUp();
-        break;
-      }
-    }
-
-    // Update send button at page load and when a send option is selected.
-    sendButton();
-    commandSend.click( function() { sendButton(); });
-  }
-};
-
-})(jQuery);
\ No newline at end of file
diff --git a/simplenews.module b/simplenews.module
index 0b11d78..47e5b59 100644
--- a/simplenews.module
+++ b/simplenews.module
@@ -36,6 +36,7 @@ define('SIMPLENEWS_PRIORITY_LOWEST', 5);
  */
 define('SIMPLENEWS_COMMAND_SEND_TEST', 0);
 define('SIMPLENEWS_COMMAND_SEND_NOW', 1);
+define('SIMPLENEWS_COMMAND_SEND_PUBLISH', 3);
 
 /**
  * NEWSLETTER SUBSCRIPTION STATUS
@@ -49,6 +50,7 @@ define('SIMPLENEWS_SUBSCRIPTION_STATUS_UNSUBSCRIBED', 0);
 define('SIMPLENEWS_STATUS_SEND_NOT', 0);
 define('SIMPLENEWS_STATUS_SEND_PENDING', 1);
 define('SIMPLENEWS_STATUS_SEND_READY', 2);
+define('SIMPLENEWS_STATUS_SEND_PUBLISH', 3);
 
 /**
  * MAIL SPOOL SENT STATUS
@@ -403,42 +405,17 @@ function simplenews_node_validate($node, $form) {
 }
 
 /**
- * Implementation of hook_node_presave().
- */
-function simplenews_node_presave($node) {
-  if (!simplenews_check_node_types($node->type)) {
-    return;
-  }
-
-  // Note that $node is NO full node object, see node_form_validate().
-  // Complete $node!
-  $newsletter = simplenews_newsletter_load($node->nid);
-  //$newsletter = simplenews_newsletter_load($node->nid, $node->vid);
-  if (!$newsletter) {
-    $newsletter = (object)simplenews_newsletter_defaults($node);
-  }
-  $node->simplenews = $newsletter;
-}
-
-/**
  * Implementation of hook_node_insert().
- *
- * // @todo simplenews_node_insert() and simplenews_node_update() have a lot in common.
- * // Solve this in a better way.
  */
 function simplenews_node_insert($node) {
   if (!simplenews_check_node_types($node->type)) {
     return;
   }
 
-  $newsletter = $node->simplenews;
+  $node->simplenews = (object)simplenews_newsletter_defaults($node);
 
-  $newsletter->nid = $node->nid;
-  $newsletter->vid = $node->vid;
-  $newsletter->status = SIMPLENEWS_STATUS_SEND_NOT;
-  $terms = simplenews_get_term_values($node);
-  $newsletter->tid = $terms[0]['tid'];
-  simplenews_newsletter_save($newsletter);
+  // $node->simplenews is set up in simplenews_node_presave().
+  simplenews_newsletter_save($node->simplenews);
 }
 
 /**
@@ -466,19 +443,32 @@ function simplenews_newsletter_defaults($node = NULL) {
 /**
  * Implementation of hook_node_update().
  */
-// @todo can we combine simplenews_node_update() and simplenews_node_insert() ?
 function simplenews_node_update($node) {
   if (!simplenews_check_node_types($node->type)) {
     return;
   }
-  // @todo Check if this is an actual 'submit' action and not update as part of e.g. 'unpublish' on the node admin page
 
-  $newsletter = $node->simplenews;
-  if (!$newsletter) {
-    $newsletter = (object)simplenews_newsletter_defaults($node);
+  $node->simplenews = simplenews_newsletter_load($node->nid);
+  if (!$node->simplenews) {
+    $node->simplenews = (object)simplenews_newsletter_defaults($node);
+  }
+  else {
+    // Update tid.
+    $terms = simplenews_get_term_values($node);
+    $node->simplenews->tid = $terms[0]['tid'];
   }
 
-  simplenews_newsletter_save($newsletter);
+  // Check if the newsletter is set to send on publish and needs to be send.
+  if ($node->simplenews->status == SIMPLENEWS_STATUS_SEND_PUBLISH && $node->status == NODE_PUBLISHED) {
+    module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
+    simplenews_update_sent_status($node);
+    simplenews_send_node($node);
+  }
+  else {
+    // simplenews_update_sent_status() already saves the node, only need to do
+    // it when not sending.
+    simplenews_newsletter_save($node->simplenews);
+  }
 }
 
 /**
@@ -3059,14 +3049,19 @@ function simplenews_node_tab_access($node) {
 /**
  * @todo
  */
-function simplenews_node_tab_send_form($form, &$form_state){
-  // Prepare
-  $node = $form_state['build_info']['args'][0];
-  $simplenews_values = (object)_simplenews_get_node_form_defaults();
-
-  if (isset($node->simplenews) && !empty($node->simplenews)) {
+function simplenews_node_tab_send_form($form, &$form_state, $node){
+  // First check if there already is a loaded simplenews object.
+  if (!empty($node->simplenews)) {
     $simplenews_values = $node->simplenews;
   }
+  // If not, try to load it based on the node id.
+  else if ($loaded = simplenews_newsletter_load($node->nid)) {
+    $simplenews_values = $loaded;
+  }
+  // If that fails too, fall back to the defaults.
+  else {
+    $simplenews_values = (object)_simplenews_get_node_form_defaults($node);
+  }
 
   $form = array();
   // We will need the node
@@ -3095,18 +3090,24 @@ function simplenews_node_tab_send_form($form, &$form_state){
   else {
     // Show newsletter sending options if newsletter has not been send yet.
     // If send a notification is shown.
-    if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_NOT) {
-
-      // @todo move add_js to form theme function. It is not (re)loaded on validation error.
-      // Add dynamic text for send button.
-      drupal_add_js(drupal_get_path('module', 'simplenews') . '/simplenews.js', 'file');
+    if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_NOT || $simplenews_values->status == SIMPLENEWS_STATUS_SEND_PUBLISH) {
 
       $options = array(
         SIMPLENEWS_COMMAND_SEND_TEST => t('Send one test newsletter to the test address'),
         SIMPLENEWS_COMMAND_SEND_NOW => t('Send newsletter'),
       );
 
-      $send_default = variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_TEST);
+      // Add option to send on publish when the node is unpublished.
+      if ($node->status == NODE_NOT_PUBLISHED) {
+        $options[SIMPLENEWS_COMMAND_SEND_PUBLISH] = t('Send newsletter when published');
+      }
+
+      if ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_PUBLISH) {
+        $send_default = SIMPLENEWS_STATUS_SEND_PUBLISH;
+      }
+      else {
+        $send_default = variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_TEST);
+      }
       $form['simplenews']['send'] = array(
         '#type' => 'radios',
         '#title' => t('Send newsletter'),
@@ -3123,7 +3124,7 @@ function simplenews_node_tab_send_form($form, &$form_state){
           '#type' => 'textfield',
           '#title' => t('Test email addresses'),
           '#description' => t('A comma-separated list of email addresses to be used as test addresses.'),
-          '#default_value' => isset($simplenews_values->test_address) ? $simplenews_values->test_address : variable_get('simplenews_test_address', $address_default),
+          '#default_value' => variable_get('simplenews_test_address', $address_default),
           '#size' => 60,
           '#maxlength' => 128,
         );
@@ -3144,7 +3145,7 @@ function simplenews_node_tab_send_form($form, &$form_state){
           'disabled' => 'disabled',
         ),
       );
-      $form['simplenews']['none']['#title'] = ($node->simplenews->status == SIMPLENEWS_STATUS_SEND_READY) ? t('This newsletter has been sent') : t('This newsletter is pending');
+      $form['simplenews']['none']['#title'] = ($simplenews_values->status == SIMPLENEWS_STATUS_SEND_READY) ? t('This newsletter has been sent') : t('This newsletter is pending');
       return $form;
     }
     $form['submit'] = array(
@@ -3192,42 +3193,67 @@ function simplenews_node_tab_send_form_submit($form, &$form_state) {
   $values = $form_state['values'];
   $node = node_load($values['nid']);
 
-  // When this node is selected for translation
-  // all translation of this node will be sent too.
+  // Send newsletter to all subscribers or send test newsletter
+  module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
+  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_NOW) {
+    simplenews_update_sent_status($node);
+    simplenews_send_node($node);
+  }
+  elseif ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_TEST) {
+    simplenews_send_test($node, $form_state['test_addresses']);
+  }
+
+  // If the selected command is send on publish, just set the newsletter status.
+  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_PUBLISH) {
+    $newsletter = simplenews_newsletter_load($node->nid);
+    if (!$newsletter) {
+      $newsletter = simplenews_newsletter_defaults($node);
+    }
+    $newsletter->status = SIMPLENEWS_STATUS_SEND_PUBLISH;
+    simplenews_newsletter_save($newsletter);
+    drupal_set_message(t('The newsletter will be sent when the content is published.'));
+  }
+}
+
+/**
+ * Update the sent status of a node.
+ *
+ * If the node part of a translation set, all corresponding translations are
+ * updated as well.
+ *
+ * @param $node
+ *   The node object to be updated.
+ * @param $status
+ *   The new status, defaults to SIMPLENEWS_STATUS_SEND_PENDING.
+ */
+function simplenews_update_sent_status($node, $status = SIMPLENEWS_STATUS_SEND_PENDING) {
+  // When this node is selected for translation, all translation of this node
+  // will be sent too.
   if (module_exists('translation') && translation_supported_type($node->type) && $node->tnid > 0) {
     if ($translations = translation_node_get_translations($node->tnid)) {
       foreach ($translations as $translation) {
-        if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_NOW) {
-          $newsletter = simplenews_newsletter_load($translation->nid);
-          if (!$newsletter) {
-            $node = node_load($translation->nid);
-            $newsletter = simplenews_newsletter_defaults($node);
-          }
-          $newsletter->status = SIMPLENEWS_STATUS_SEND_PENDING;
-          simplenews_newsletter_save($newsletter);
+        $newsletter = simplenews_newsletter_load($translation->nid);
+        if (!$newsletter) {
+          $node = node_load($translation->nid);
+          $newsletter = (object) simplenews_newsletter_defaults($node);
         }
+        $newsletter->status = SIMPLENEWS_STATUS_SEND_PENDING;
+        simplenews_newsletter_save($newsletter);
       }
     }
   }
-  else {
-    if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_NOW) {
-      $newsletter = simplenews_newsletter_load($node->nid);
-      if (!$newsletter) {
-        $newsletter = simplenews_newsletter_defaults($node);
-      }
-      $newsletter->status = SIMPLENEWS_STATUS_SEND_PENDING;
-      simplenews_newsletter_save($newsletter);
-    }
-  }
 
-  // Send newsletter to all subscribers or send test newsletter
-  module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
-  if ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_NOW) {
-    simplenews_send_node($node);
+  if (!empty($node->simplenews)) {
+    $newsletter = $node->simplenews;
   }
-  elseif ($values['simplenews']['send'] == SIMPLENEWS_COMMAND_SEND_TEST) {
-    simplenews_send_test($node, $form_state['test_addresses']);
+  else {
+    $newsletter = simplenews_newsletter_load($node->nid);
   }
+  if (!$newsletter) {
+    $newsletter = (object)simplenews_newsletter_defaults($node);
+  }
+  $newsletter->status = SIMPLENEWS_STATUS_SEND_PENDING;
+  simplenews_newsletter_save($newsletter);
 }
 
 /**
diff --git a/tests/simplenews.test b/tests/simplenews.test
index 03d471c..a89faeb 100644
--- a/tests/simplenews.test
+++ b/tests/simplenews.test
@@ -739,7 +739,6 @@ class SimpleNewsAdministrationTestCase extends SimplenewsTestCase {
 
     $this->clickLink(t('Newsletter'));
     $this->assertText(t('Send newsletter'));
-    // @todo: The button text is changed with JS and is originally "Submit".
     $this->drupalPost(NULL, array(), t('Submit'));
 
     $mails = $this->drupalGetMails();
@@ -994,3 +993,321 @@ class SimpleNewsUpgradePath62TestCase extends UpgradePathTestCase {
 
   }
 }
+
+
+/**
+ * Test cases for creating and sending newsletters.
+ */
+class SimplenewsSendTestCase extends SimplenewsTestCase {
+  /**
+   * Implementation of getInfo().
+   */
+  function getInfo() {
+    return array(
+      'name' => t('Sending newsletters'),
+      'description' => t('Creating and sending of newsletters, different send processes (with/without cron, send on publish)'),
+      'group' => t('Simplenews'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $this->user = $this->drupalCreateUser(array('administer newsletters', 'send newsletter', 'administer nodes', 'administer simplenews subscriptions', 'create simplenews content', 'edit any simplenews content', 'view own unpublished content'));
+    $this->drupalLogin($this->user);
+
+    // Subscribe a few users.
+    $this->subscribers = array();
+    for ($i = 0; $i < 5; $i++) {
+      $mail = $this->randomEmail();
+      $this->subscribers[$mail] = $mail;
+    }
+
+    $delimiters = array(',', ' ', "\n");
+
+    $this->drupalGet('admin/people/simplenews');
+    $this->clickLink(t('Mass subscribe'));
+    $edit = array(
+      'emails' => implode(',', $this->subscribers),
+      // @todo: Don't hardcode the default tid.
+      '1' => TRUE,
+    );
+    $this->drupalPost(NULL, $edit, t('Subscribe'));
+  }
+
+  /**
+   * Send a newsletter using cron.
+   */
+  function testSendNowNoCron() {
+    // Disable cron.
+    variable_set('simplenews_use_cron', FALSE);
+
+    // Verify that the newsletter settings are shown.
+    $this->drupalGet('node/add/simplenews');
+    $this->assertText(t('Newsletter category'));
+
+    $edit = array(
+      'title' => $this->randomName(),
+    );
+    $this->drupalPost(NULL, $edit, ('Save'));
+    $this->assertTrue(preg_match('|node/(\d+)$|', $this->getUrl(), $matches), 'Node created');
+    $node = node_load($matches[1]);
+
+    $this->clickLink(t('Newsletter'));
+    $this->assertText(t('Send one test newsletter to the test address'));
+    $this->assertText(t('Send newsletter'));
+    $this->assertNoText(t('Send newsletter when published'), t('Send on publish is not shown for published nodes.'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_NOT, $newsletter->status, t('Newsletter not sent yet.'));
+
+    // Send now.
+    $this->drupalPost(NULL, array('simplenews[send]' => SIMPLENEWS_COMMAND_SEND_NOW), t('Submit'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_READY, $newsletter->status, t('Newsletter sending finished'));
+
+    // Verify mails.
+    $mails = $this->drupalGetMails();
+    $this->assertEqual(5, count($mails), t('All mails were sent.'));
+    foreach ($mails as $mail) {
+      $this->assertEqual($mail['subject'], '[Drupal newsletter] ' . $edit['title'], t('Mail has correct subject'));
+      $this->assertTrue(isset($this->subscribers[$mail['to']]), t('Found valid recipient'));
+      unset($this->subscribers[$mail['to']]);
+    }
+    $this->assertEqual(0, count($this->subscribers), t('all subscribers have been received a mail'));
+  }
+
+  /**
+   * Send a newsletter using cron and a low throttle.
+   */
+  function testSendNowCronThrottle() {
+
+    variable_set('simplenews_throttle', 3);
+
+    // Verify that the newsletter settings are shown.
+    $this->drupalGet('node/add/simplenews');
+    $this->assertText(t('Newsletter category'));
+
+    $edit = array(
+      'title' => $this->randomName(),
+    );
+    $this->drupalPost(NULL, $edit, ('Save'));
+    $this->assertTrue(preg_match('|node/(\d+)$|', $this->getUrl(), $matches), 'Node created');
+    $node = node_load($matches[1]);
+
+    $this->clickLink(t('Newsletter'));
+    $this->assertText(t('Send one test newsletter to the test address'));
+    $this->assertText(t('Send newsletter'));
+    $this->assertNoText(t('Send newsletter when published'), t('Send on publish is not shown for published nodes.'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_NOT, $newsletter->status, t('Newsletter not sent yet.'));
+
+    // Send now.
+    $this->drupalPost(NULL, array('simplenews[send]' => SIMPLENEWS_COMMAND_SEND_NOW), t('Submit'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_PENDING, $newsletter->status, t('Newsletter sending pending.'));
+
+    // Verify that no mails have been sent yet.
+    $mails = $this->drupalGetMails();
+    $this->assertEqual(0, count($mails), t('No mails were sent yet.'));
+
+    $spooled = db_query('SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField();
+    $this->assertEqual(5, $spooled, t('5 mails have been added to the mail spool'));
+
+    // Run cron for the first time.
+    simplenews_cron();
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_PENDING, $newsletter->status, t('Newsletter sending pending.'));
+
+    $spooled = db_query('SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField();
+    $this->assertEqual(2, $spooled, t('2 mails remaining in spool.'));
+
+    // Run cron for the second time.
+    simplenews_cron();
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_READY, $newsletter->status, t('Newsletter sending finished.'));
+
+    $spooled = db_query('SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField();
+    $this->assertEqual(0, $spooled, t('No mails remaining in spool.'));
+
+    // Verify mails.
+    $mails = $this->drupalGetMails();
+    $this->assertEqual(5, count($mails), t('All mails were sent.'));
+    foreach ($mails as $mail) {
+      $this->assertEqual($mail['subject'], '[Drupal newsletter] ' . $edit['title'], t('Mail has correct subject'));
+      $this->assertTrue(isset($this->subscribers[$mail['to']]), t('Found valid recipient'));
+      unset($this->subscribers[$mail['to']]);
+    }
+    $this->assertEqual(0, count($this->subscribers), t('all subscribers have been received a mail'));
+  }
+
+  /**
+   * Send a newsletter without using cron.
+   */
+  function testSendNowCron() {
+
+    // Verify that the newsletter settings are shown.
+    $this->drupalGet('node/add/simplenews');
+    $this->assertText(t('Newsletter category'));
+
+    $edit = array(
+      'title' => $this->randomName(),
+    );
+    $this->drupalPost(NULL, $edit, ('Save'));
+    $this->assertTrue(preg_match('|node/(\d+)$|', $this->getUrl(), $matches), 'Node created');
+    $node = node_load($matches[1]);
+
+    $this->clickLink(t('Newsletter'));
+    $this->assertText(t('Send one test newsletter to the test address'));
+    $this->assertText(t('Send newsletter'));
+    $this->assertNoText(t('Send newsletter when published'), t('Send on publish is not shown for published nodes.'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_NOT, $newsletter->status, t('Newsletter not sent yet.'));
+
+    // Send now.
+    $this->drupalPost(NULL, array('simplenews[send]' => SIMPLENEWS_COMMAND_SEND_NOW), t('Submit'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_PENDING, $newsletter->status, t('Newsletter sending pending.'));
+
+    // Verify that no mails have been sent yet.
+    $mails = $this->drupalGetMails();
+    $this->assertEqual(0, count($mails), t('No mails were sent yet.'));
+
+    $spooled = db_query('SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField();
+    $this->assertEqual(5, $spooled, t('5 mails have been added to the mail spool'));
+
+    // Run cron.
+    simplenews_cron();
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_READY, $newsletter->status, t('Newsletter sending finished.'));
+
+    $spooled = db_query('SELECT COUNT(*) FROM {simplenews_mail_spool} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField();
+    $this->assertEqual(0, $spooled, t('No mails remaining in spool.'));
+
+    // Verify mails.
+    $mails = $this->drupalGetMails();
+    $this->assertEqual(5, count($mails), t('All mails were sent.'));
+    foreach ($mails as $mail) {
+      $this->assertEqual($mail['subject'], '[Drupal newsletter] ' . $edit['title'], t('Mail has correct subject'));
+      $this->assertTrue(isset($this->subscribers[$mail['to']]), t('Found valid recipient'));
+      unset($this->subscribers[$mail['to']]);
+    }
+    $this->assertEqual(0, count($this->subscribers), t('all subscribers have been received a mail'));
+  }
+
+  /**
+   * Send a newsletter on publish without using cron.
+   */
+  function testSendPublishNoCron() {
+    // Disable cron.
+    variable_set('simplenews_use_cron', FALSE);
+
+    // Verify that the newsletter settings are shown.
+    $this->drupalGet('node/add/simplenews');
+    $this->assertText(t('Newsletter category'));
+
+    $edit = array(
+      'title' => $this->randomName(),
+      'status' => FALSE,
+    );
+    $this->drupalPost(NULL, $edit, ('Save'));
+    $this->assertTrue(preg_match('|node/(\d+)$|', $this->getUrl(), $matches), 'Node created');
+    $node = node_load($matches[1]);
+
+    $this->clickLink(t('Newsletter'));
+    $this->assertText(t('Send one test newsletter to the test address'));
+    $this->assertText(t('Send newsletter'));
+    $this->assertText(t('Send newsletter when published'), t('Send on publish is shown'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_NOT, $newsletter->status, t('Newsletter not sent yet.'));
+
+    // Send now.
+    $this->drupalPost(NULL, array('simplenews[send]' => SIMPLENEWS_COMMAND_SEND_PUBLISH), t('Submit'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_PUBLISH, $newsletter->status, t('Newsletter set up for sending on publish.'));
+
+    $this->clickLink(t('Edit'));
+    $update = array(
+      'status' => TRUE,
+    );
+    $this->drupalPost(NULL, $update, t('Save'));
+
+    // Verify state.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_READY, $newsletter->status, t('Newsletter sending finished'));
+    // @todo test sent subscriber count.
+
+    // Verify mails.
+    $mails = $this->drupalGetMails();
+    $this->assertEqual(5, count($mails), t('All mails were sent.'));
+    foreach ($mails as $mail) {
+      $this->assertEqual($mail['subject'], '[Drupal newsletter] ' . $edit['title'], t('Mail has correct subject'));
+      $this->assertTrue(isset($this->subscribers[$mail['to']]), t('Found valid recipient'));
+      unset($this->subscribers[$mail['to']]);
+    }
+    $this->assertEqual(0, count($this->subscribers), t('all subscribers have been received a mail'));
+  }
+
+  function testUpdateNewsletter() {
+    // Create a second category.
+    $this->drupalGet('admin/config/services/simplenews');
+    $this->clickLink(t('Add newsletter category'));
+    $edit = array(
+      'name' => $this->randomName(),
+      'description' => $this->randomString(20),
+    );
+    $this->drupalPost(NULL, $edit, t('Save'));
+
+    $this->drupalGet('node/add/simplenews');
+    $this->assertText(t('Newsletter category'));
+
+    $edit = array(
+      'title' => $this->randomName(),
+      // @todo avoid hardcoding the term id.
+      'field_simplenews_term[und]' => 1,
+    );
+    $this->drupalPost(NULL, $edit, ('Save'));
+    $this->assertTrue(preg_match('|node/(\d+)$|', $this->getUrl(), $matches), 'Node created.');
+    $node = node_load($matches[1]);
+
+    // Verify newsletter.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_NOT, $newsletter->status, t('Newsletter sending not started.'));
+    $this->assertEqual(1, $newsletter->tid, t('Newsletter has tid 1'));
+
+    $this->clickLink(t('Edit'));
+    $update = array(
+      'field_simplenews_term[und]' => 2,
+    );
+    $this->drupalPost(NULL, $update, t('Save'));
+
+    // Verify newsletter.
+    $newsletter = simplenews_newsletter_load($node->nid);
+    $this->assertEqual(SIMPLENEWS_STATUS_SEND_NOT, $newsletter->status, t('Newsletter sending not started.'));
+    $this->assertEqual(2, $newsletter->tid, t('Newsletter has tid 2.'));
+  }
+}
