You are here

function SimpleNewsAdministrationTestCase::testSubscriptionManagement in Simplenews 7.2

Same name and namespace in other branches
  1. 6.2 tests/simplenews.test \SimpleNewsAdministrationTestCase::testSubscriptionManagement()
  2. 7 tests/simplenews.test \SimpleNewsAdministrationTestCase::testSubscriptionManagement()

Test newsletter subscription management.

Steps performed:

File

tests/simplenews.test, line 1337
Simplenews test functions.

Class

SimpleNewsAdministrationTestCase
@todo: Newsletter node create, send draft, send final

Code

function testSubscriptionManagement() {
  $admin_user = $this
    ->drupalCreateUser(array(
    'administer newsletters',
    'administer simplenews settings',
    'administer simplenews subscriptions',
  ));
  $this
    ->drupalLogin($admin_user);

  // Create a second newsletter.
  $edit = array(
    'name' => $name = $this
      ->randomName(),
  );
  $this
    ->drupalPost('admin/config/services/simplenews/add', $edit, t('Save'));

  // Add a number of users to each newsletter separately and then add another
  // bunch to both.
  $subscribers = array();
  drupal_static_reset('simplenews_newsletter_load_multiple');
  $groups = array();
  $newsletters = simplenews_newsletter_get_all();
  foreach ($newsletters as $newsletter) {
    $groups[$newsletter->newsletter_id] = array(
      $newsletter->newsletter_id,
    );
  }
  $groups['all'] = array_keys($groups);
  $subscribers_flat = array();
  foreach ($groups as $key => $group) {
    for ($i = 0; $i < 5; $i++) {
      $mail = $this
        ->randomEmail();
      $subscribers[$key][$mail] = $mail;
      $subscribers_flat[$mail] = $mail;
    }
  }

  // Create a user and assign him one of the mail addresses of the all group.
  $user = $this
    ->drupalCreateUser(array(
    'subscribe to newsletters',
  ));

  // Make sure that user_save() does not update the user object, as it will
  // override the pass_raw property which we'll need to log this user in
  // later on.
  $user_mail = current($subscribers['all']);
  user_save(clone $user, array(
    'mail' => $user_mail,
  ));
  $delimiters = array(
    ',',
    ' ',
    "\n",
  );
  $this
    ->drupalGet('admin/people/simplenews');
  $i = 0;
  foreach ($groups as $key => $group) {
    $this
      ->clickLink(t('Mass subscribe'));
    $edit = array(
      // Implode with a different, supported delimiter for each group.
      'emails' => implode($delimiters[$i++], $subscribers[$key]),
    );
    foreach ($group as $newsletter_id) {
      $edit['newsletters[' . $newsletter_id . ']'] = TRUE;
    }
    $this
      ->drupalPost(NULL, $edit, t('Subscribe'));
  }

  // The user to which the mail was assigned should be listed too.
  $this
    ->assertText($user->name);

  // Verify that all addresses are displayed in the table.
  $mail_addresses = $this
    ->xpath('//tr/td[2]');
  $this
    ->assertEqual(15, count($mail_addresses));
  foreach ($mail_addresses as $mail_address) {
    $mail_address = (string) $mail_address;
    $this
      ->assertTrue(isset($subscribers_flat[$mail_address]));
    unset($subscribers_flat[$mail_address]);
  }

  // All entries of the array should be removed by now.
  $this
    ->assertTrue(empty($subscribers_flat));

  // Limit list to subscribers of the first newsletter only.
  reset($groups);
  $first = key($groups);

  // Build a flat list of the subscribers of this list.
  $subscribers_flat = array_merge($subscribers[$first], $subscribers['all']);
  $edit = array(
    'list' => 'newsletter_id-' . $first,
  );
  $this
    ->drupalPost(NULL, $edit, t('Filter'));

  // Verify that all addresses are displayed in the table.
  $mail_addresses = $this
    ->xpath('//tr/td[2]');
  $this
    ->assertEqual(10, count($mail_addresses));
  foreach ($mail_addresses as $mail_address) {
    $mail_address = (string) $mail_address;
    $this
      ->assertTrue(isset($subscribers_flat[$mail_address]));
    unset($subscribers_flat[$mail_address]);
  }

  // All entries of the array should be removed by now.
  $this
    ->assertTrue(empty($subscribers_flat));

  // Filter a single mail address, the one assigned to a user.
  $edit = array(
    'email' => drupal_substr(current($subscribers['all']), 0, 4),
  );
  $this
    ->drupalPost(NULL, $edit, t('Filter'));
  $rows = $this
    ->xpath('//tbody/tr');
  $this
    ->assertEqual(1, count($rows));
  $this
    ->assertEqual(current($subscribers['all']), (string) $rows[0]->td[1]);
  $this
    ->assertEqual($user->name, (string) $rows[0]->td[2]->a);

  // Reset the filter.
  $this
    ->drupalPost(NULL, array(), t('Reset'));

  // Test mass-unsubscribe, unsubscribe one from the first group and one from
  // the all group, but only from the first newsletter.
  $first_mail = array_rand($subscribers[$first]);
  $all_mail = array_rand($subscribers['all']);
  unset($subscribers[$first][$first_mail]);
  $edit = array(
    'emails' => $first_mail . ', ' . $all_mail,
    'newsletters[' . $first . ']' => TRUE,
  );
  $this
    ->clickLink(t('Mass unsubscribe'));
  $this
    ->drupalPost(NULL, $edit, t('Unsubscribe'));

  // The all mail is still displayed because it's still subscribed to the
  // second newsletter. Reload the page to get rid of the confirmation
  // message.
  $this
    ->drupalGet('admin/people/simplenews');
  $this
    ->assertNoText($first_mail);
  $this
    ->assertText($all_mail);

  // Limit to first newsletter, the all mail shouldn't be shown anymore.
  $edit = array(
    'list' => 'newsletter_id-' . $first,
  );
  $this
    ->drupalPost(NULL, $edit, t('Filter'));
  $this
    ->assertNoText($first_mail);
  $this
    ->assertNoText($all_mail);

  // Check exporting.
  $this
    ->clickLink(t('Export'));
  $this
    ->drupalPost(NULL, array(
    'newsletters[' . $first . ']' => TRUE,
  ), t('Export'));
  $export_field = $this
    ->xpath($this
    ->constructFieldXpath('name', 'emails'));
  $exported_mails = (string) $export_field[0];
  foreach ($subscribers[$first] as $mail) {
    $this
      ->assertTrue(strpos($exported_mails, $mail) !== FALSE, t('Mail address exported correctly.'));
  }
  foreach ($subscribers['all'] as $mail) {
    if ($mail != $all_mail) {
      $this
        ->assertTrue(strpos($exported_mails, $mail) !== FALSE, t('Mail address exported correctly.'));
    }
    else {
      $this
        ->assertFALSE(strpos($exported_mails, $mail) !== FALSE, t('Unsubscribed mail address not exported.'));
    }
  }

  // Only export unsubscribed mail addresses.
  $edit = array(
    'subscribed[subscribed]' => FALSE,
    'subscribed[unsubscribed]' => TRUE,
    'newsletters[' . $first . ']' => TRUE,
  );
  $this
    ->drupalPost(NULL, $edit, t('Export'));
  $export_field = $this
    ->xpath($this
    ->constructFieldXpath('name', 'emails'));
  $exported_mails = (string) $export_field[0];
  $exported_mails = explode(', ', $exported_mails);
  $this
    ->assertEqual(2, count($exported_mails));
  $this
    ->assertTrue(in_array($all_mail, $exported_mails));
  $this
    ->assertTrue(in_array($first_mail, $exported_mails));

  // Make sure there are unconfirmed subscriptions.
  $unconfirmed = array();
  $unconfirmed[] = $this
    ->randomEmail();
  $unconfirmed[] = $this
    ->randomEmail();
  foreach ($unconfirmed as $mail) {
    simplenews_subscribe($mail, $first, TRUE);
  }

  // Only export unconfirmed mail addresses.
  $edit = array(
    'subscribed[subscribed]' => FALSE,
    'subscribed[unconfirmed]' => TRUE,
    'subscribed[unsubscribed]' => FALSE,
    'newsletters[' . $first . ']' => TRUE,
  );
  $this
    ->drupalPost(NULL, $edit, t('Export'));
  $export_field = $this
    ->xpath($this
    ->constructFieldXpath('name', 'emails'));
  $exported_mails = (string) $export_field[0];
  $exported_mails = explode(', ', $exported_mails);
  $this
    ->assertEqual(2, count($exported_mails));
  $this
    ->assertTrue(in_array($unconfirmed[0], $exported_mails));
  $this
    ->assertTrue(in_array($unconfirmed[1], $exported_mails));

  // Make sure the user is subscribed to the first newsletter_id.
  simplenews_subscribe($user_mail, $first, FALSE);
  module_load_include('inc', 'simplenews', 'includes/simplenews.admin');
  $before_count = simplenews_count_subscriptions($first);

  // Block the user.
  user_save(clone $user, array(
    'status' => 0,
  ));
  $this
    ->drupalGet('admin/people/simplenews');

  // Verify updated subscriptions count.
  drupal_static_reset('simplenews_count_subscriptions');
  $after_count = simplenews_count_subscriptions($first);
  $this
    ->assertEqual($before_count - 1, $after_count, t('Blocked users are not counted in subscription count.'));

  // Test mass subscribe with previously unsubscribed users.
  for ($i = 0; $i < 3; $i++) {
    $tested_subscribers[] = $this
      ->randomEmail();
  }
  simplenews_subscribe($tested_subscribers[0], $first, FALSE);
  simplenews_subscribe($tested_subscribers[1], $first, FALSE);
  simplenews_unsubscribe($tested_subscribers[0], $first, FALSE);
  simplenews_unsubscribe($tested_subscribers[1], $first, FALSE);
  $unsubscribed = implode(', ', array_slice($tested_subscribers, 0, 2));
  $edit = array(
    'emails' => implode(', ', $tested_subscribers),
    'newsletters[' . $first . ']' => TRUE,
  );
  $this
    ->drupalPost('admin/people/simplenews/import', $edit, t('Subscribe'));
  entity_get_controller('simplenews_subscriber')
    ->resetCache();
  drupal_static_reset('simplenews_user_is_subscribed');
  $this
    ->assertFalse(simplenews_user_is_subscribed($tested_subscribers[0], $first, t('Subscriber not resubscribed through mass subscription.')));
  $this
    ->assertFalse(simplenews_user_is_subscribed($tested_subscribers[1], $first, t('Subscriber not resubscribed through mass subscription.')));
  $this
    ->assertTrue(simplenews_user_is_subscribed($tested_subscribers[2], $first, t('Subscriber subscribed through mass subscription.')));
  $substitutes = array(
    '@name' => check_plain(simplenews_newsletter_load($first)->name),
    '@mail' => $unsubscribed,
  );
  $this
    ->assertText(t('The following addresses were skipped because they have previously unsubscribed from @name: @mail.', $substitutes));
  $this
    ->assertText(t("If you would like to resubscribe them, use the 'Force resubscription' option."));

  // Test mass subscribe with previously unsubscribed users and force
  // resubscription.
  $tested_subscribers[2] = $this
    ->randomEmail();
  $edit = array(
    'emails' => implode(', ', $tested_subscribers),
    'newsletters[' . $first . ']' => TRUE,
    'resubscribe' => TRUE,
  );
  $this
    ->drupalPost('admin/people/simplenews/import', $edit, t('Subscribe'));
  drupal_static_reset('simplenews_user_is_subscribed');
  entity_get_controller('simplenews_subscriber')
    ->resetCache();
  $this
    ->assertTrue(simplenews_user_is_subscribed($tested_subscribers[0], $first, t('Subscriber resubscribed trough mass subscription.')));
  $this
    ->assertTrue(simplenews_user_is_subscribed($tested_subscribers[1], $first, t('Subscriber resubscribed trough mass subscription.')));
  $this
    ->assertTrue(simplenews_user_is_subscribed($tested_subscribers[2], $first, t('Subscriber subscribed trough mass subscription.')));

  // Delete newsletter.
  entity_get_controller('simplenews_newsletter')
    ->resetCache();
  $this
    ->drupalPost('admin/config/services/simplenews/categories/' . $first . '/edit', array(), t('Delete'));
  $this
    ->drupalPost(NULL, array(), t('Delete'));
  $this
    ->assertText(t('All subscriptions to newsletter @newsletter have been deleted.', array(
    '@newsletter' => $newsletters[$first]->name,
  )));

  // Verify that all related data has been deleted.
  $this
    ->assertFalse(simplenews_newsletter_load($first));
  $this
    ->assertFalse(db_query('SELECT newsletter_id FROM {simplenews_newsletter} WHERE newsletter_id = :newsletter_id', array(
    ':newsletter_id' => $first,
  ))
    ->fetchField());
  $this
    ->assertFalse(db_query('SELECT * FROM {block} WHERE module = :module AND delta = :newsletter_id', array(
    ':module' => 'simplenews',
    ':newsletter_id' => $first,
  ))
    ->fetchField());

  // Verify that all subscriptions of that newsletter have been removed.
  $this
    ->drupalGet('admin/people/simplenews');
  foreach ($subscribers[$first] as $mail) {
    $this
      ->assertNoText($mail);
  }

  // Reset list and click on the first subscriber.
  $this
    ->drupalPost(NULL, array(), t('Reset'));
  $this
    ->clickLink(t('edit'));

  // Get the subscriber id from the path.
  $this
    ->assertTrue(preg_match('|admin/people/simplenews/users/edit/(\\d+)$|', $this
    ->getUrl(), $matches), 'Subscriber found');
  $subscriber = simplenews_subscriber_load($matches[1]);
  $this
    ->assertText(t('Subscriptions for @mail', array(
    '@mail' => $subscriber->mail,
  )));
  $this
    ->assertFieldChecked('edit-activated--2');

  // Disable account.
  $edit = array(
    'activated' => FALSE,
  );
  $this
    ->drupalPost(NULL, $edit, t('Update'));
  entity_get_controller('simplenews_subscriber')
    ->resetCache();
  drupal_static_reset('simplenews_user_is_subscribed');
  $this
    ->assertFalse(simplenews_user_is_subscribed($subscriber->mail, $this
    ->getRandomNewsletter(), t('Subscriber is not active')));

  // Re-enable account.
  $this
    ->drupalGet('admin/people/simplenews/users/edit/' . $subscriber->snid);
  $this
    ->assertText(t('Subscriptions for @mail', array(
    '@mail' => $subscriber->mail,
  )));
  $this
    ->assertNoFieldChecked('edit-activated--2');
  $edit = array(
    'activated' => TRUE,
  );
  $this
    ->drupalPost(NULL, $edit, t('Update'));
  entity_get_controller('simplenews_subscriber')
    ->resetCache();
  drupal_static_reset('simplenews_user_is_subscribed');
  $this
    ->assertTrue(simplenews_user_is_subscribed($subscriber->mail, $this
    ->getRandomNewsletter(), t('Subscriber is active again.')));

  // Remove the newsletter.
  $this
    ->drupalGet('admin/people/simplenews/users/edit/' . $subscriber->snid);
  $this
    ->assertText(t('Subscriptions for @mail', array(
    '@mail' => $subscriber->mail,
  )));
  $edit = array(
    'newsletters[' . reset($subscriber->newsletter_ids) . ']' => FALSE,
  );
  $this
    ->drupalPost(NULL, $edit, t('Update'));
  entity_get_controller('simplenews_subscriber')
    ->resetCache();
  drupal_static_reset('simplenews_user_is_subscribed');
  $this
    ->assertFalse(simplenews_user_is_subscribed($subscriber->mail, reset($subscriber->newsletter_ids), t('Subscriber not subscribed anymore.')));

  // @todo Test Admin subscriber edit preferred language $subscription->language
  // Register a subscriber with an insecure e-mail address through the API
  // and make sure the address is correctly encoded.
  $xss_mail = "<script>alert('XSS');</script>";
  simplenews_subscribe($xss_mail, $this
    ->getRandomNewsletter(), FALSE);
  $this
    ->drupalGet('admin/people/simplenews');
  $this
    ->assertNoRaw($xss_mail);
  $this
    ->assertRaw(check_plain($xss_mail));
  $xss_subscriber = simplenews_subscriber_load_by_mail($xss_mail);
  $this
    ->drupalGet('admin/people/simplenews/users/edit/' . $xss_subscriber->snid);
  $this
    ->assertNoRaw($xss_mail);
  $this
    ->assertRaw(check_plain($xss_mail));
}