You are here

function SimplenewsSubscribeTest::testSubscribeMultiple in Simplenews 8

Subscribe to multiple newsletters at the same time.

File

src/Tests/SimplenewsSubscribeTest.php, line 26
Simplenews subscribe test functions.

Class

SimplenewsSubscribeTest
(un)subscription of anonymous and authenticated users.

Namespace

Drupal\simplenews\Tests

Code

function testSubscribeMultiple() {
  $admin_user = $this
    ->drupalCreateUser(array(
    'administer blocks',
    'administer content types',
    'administer nodes',
    'access administration pages',
    'administer permissions',
    'administer newsletters',
    'administer simplenews subscriptions',
  ));
  $this
    ->drupalLogin($admin_user);
  $this
    ->drupalGet('admin/config/services/simplenews');
  for ($i = 0; $i < 5; $i++) {
    $this
      ->clickLink(t('Add newsletter'));
    $name = $this
      ->randomMachineName();
    $edit = array(
      'name' => $name,
      'id' => strtolower($name),
      'description' => $this
        ->randomString(20),
      'opt_inout' => 'double',
    );
    $this
      ->drupalPostForm(NULL, $edit, t('Save'));
  }
  $newsletters = simplenews_newsletter_get_all();
  $this
    ->drupalLogout();
  $enable = array_rand($newsletters, 3);
  $mail = $this
    ->randomEmail(8);
  $edit = array(
    'mail[0][value]' => $mail,
  );
  foreach ($enable as $newsletter_id) {
    $edit['subscriptions[' . $newsletter_id . ']'] = TRUE;
  }
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Subscribe'));
  $this
    ->assertText(t('You will receive a confirmation e-mail shortly containing further instructions on how to complete your subscription.'), t('Subscription confirmation e-mail sent.'));

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    $this
      ->assertMailText(t('Subscribe to @name', array(
      '@name' => $newsletter->name,
    )), 0, in_array($newsletter_id, $enable));
  }
  $mails = $this
    ->drupalGetMails();
  $this
    ->assertEqual($mails[0]['from'], 'simpletest@example.com');
  $this
    ->assertEqual($mails[0]['headers']['From'], '"Drupal" <simpletest@example.com>');
  $confirm_url = $this
    ->extractConfirmationLink($this
    ->getMail(0));
  $this
    ->drupalGet($confirm_url);
  $this
    ->assertRaw(t('Are you sure you want to confirm the following subscription changes for %user?', array(
    '%user' => simplenews_mask_mail($mail),
  )), t('Subscription confirmation found.'));

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    if (in_array($newsletter_id, $enable)) {
      $this
        ->assertText(t('Subscribe to @name', array(
        '@name' => $newsletter->name,
      )));
    }
    else {
      $this
        ->assertNoText(t('Subscribe to @name', array(
        '@name' => $newsletter->name,
      )));
    }
  }
  $this
    ->drupalPostForm($confirm_url, array(), t('Confirm'));
  $this
    ->assertRaw(t('Subscription changes confirmed for %user.', array(
    '%user' => $mail,
  )), t('Anonymous subscriber added to newsletter'));

  /** @var \Drupal\simplenews\Subscription\SubscriptionManagerInterface $subscription_manager */
  $subscription_manager = \Drupal::service('simplenews.subscription_manager');
  $subscription_manager
    ->reset();
  $subscriber_storage = \Drupal::entityTypeManager()
    ->getStorage('simplenews_subscriber');
  $subscriber_storage
    ->resetCache();

  // Verify subscription changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    $is_subscribed = $subscription_manager
      ->isSubscribed($mail, $newsletter_id);
    $subscription_newsletter = $subscriber_storage
      ->getSubscriptionsByNewsletter($newsletter_id);
    if (in_array($newsletter_id, $enable)) {
      $this
        ->assertTrue($is_subscribed);
      $this
        ->assertEqual(1, count($subscription_newsletter));
    }
    else {
      $this
        ->assertFalse($is_subscribed);
      $this
        ->assertEqual(0, count($subscription_newsletter));
    }
  }

  // Go to the manage page and submit without changes.
  $subscriber = simplenews_subscriber_load_by_mail($mail);
  $hash = simplenews_generate_hash($subscriber
    ->getMail(), 'manage');
  $this
    ->drupalPostForm('newsletter/subscriptions/' . $subscriber
    ->id() . '/' . REQUEST_TIME . '/' . $hash, array(), t('Update'));
  $this
    ->assertText(t('The newsletter subscriptions for @mail have been updated.', array(
    '@mail' => $mail,
  )));
  $this
    ->assertEqual(1, count($this
    ->drupalGetMails()), t('No confirmation mails have been sent.'));

  // Unsubscribe from two of the three enabled newsletters.
  $disable = array_rand(array_flip($enable), 2);
  $edit = array(
    'mail[0][value]' => $mail,
  );
  foreach ($disable as $newsletter_id) {
    $edit['subscriptions[' . $newsletter_id . ']'] = TRUE;
  }
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Unsubscribe'));
  $this
    ->assertText(t('You will receive a confirmation e-mail shortly containing further instructions on how to cancel your subscription.'), t('Subscription confirmation e-mail sent.'));

  // Unsubscribe with no confirmed email.
  $subscription_manager = \Drupal::service('simplenews.subscription_manager');
  try {
    $subscription_manager
      ->unsubscribe('new@email.com', $newsletter_id, FALSE);
    $this
      ->fail('Exception not thrown.');
  } catch (\Exception $e) {
    $this
      ->assertEqual($e
      ->getMessage(), 'The subscriber does not exist.');
  }

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    $this
      ->assertMailText(t('Unsubscribe from @name', array(
      '@name' => $newsletter->name,
    )), 1, in_array($newsletter_id, $disable));
  }
  $confirm_url = $this
    ->extractConfirmationLink($this
    ->getMail(1));
  $this
    ->drupalGet($confirm_url);
  $this
    ->assertRaw(t('Are you sure you want to confirm the following subscription changes for %user?', array(
    '%user' => simplenews_mask_mail($mail),
  )), t('Subscription confirmation found.'));

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    if (in_array($newsletter_id, $disable)) {
      $this
        ->assertText(t('Unsubscribe from @name', array(
        '@name' => $newsletter->name,
      )));
    }
    else {
      $this
        ->assertNoText(t('Unsubscribe from @name', array(
        '@name' => $newsletter->name,
      )));
    }
  }
  $this
    ->drupalPostForm($confirm_url, array(), t('Confirm'));
  $this
    ->assertRaw(t('Subscription changes confirmed for %user.', array(
    '%user' => $mail,
  )), t('Anonymous subscriber added to newsletter'));

  // Verify subscription changes.
  $subscriber_storage
    ->resetCache();
  $subscription_manager
    ->reset();
  $still_enabled = array_diff($enable, $disable);
  foreach ($newsletters as $newsletter_id => $newsletter) {
    $is_subscribed = $subscription_manager
      ->isSubscribed($mail, $newsletter_id);
    if (in_array($newsletter_id, $still_enabled)) {
      $this
        ->assertTrue($is_subscribed);
    }
    else {
      $this
        ->assertFalse($is_subscribed);
    }
  }

  // Make sure that a single change results in a non-multi confirmation mail.
  $newsletter_id = reset($disable);
  $edit = array(
    'mail[0][value]' => $mail,
    'subscriptions[' . $newsletter_id . ']' => TRUE,
  );
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Subscribe'));
  $this
    ->getMail(2);

  // Load simplenews settings config object.
  $config = $this
    ->config('simplenews.settings');

  // Change behavior to always use combined mails.
  $config
    ->set('subscription.use_combined', 'always');
  $config
    ->save();
  $edit = array(
    'mail[0][value]' => $mail,
    'subscriptions[' . $newsletter_id . ']' => TRUE,
  );
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Subscribe'));
  $this
    ->getMail(3);

  // Change behavior to never, should send two separate mails.
  $config
    ->set('subscription.use_combined', 'never');
  $config
    ->save();
  $edit = array(
    'mail[0][value]' => $mail,
  );
  foreach ($disable as $newsletter_id) {
    $edit['subscriptions[' . $newsletter_id . ']'] = TRUE;
  }
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Subscribe'));
  $this
    ->assertText(t('You will receive a confirmation e-mail shortly containing further instructions on how to complete your subscription.'), t('Subscription confirmation e-mail sent.'));
  $this
    ->extractConfirmationLink($this
    ->getMail(4));
  $this
    ->extractConfirmationLink($this
    ->getMail(5));

  // Make sure that the /ok suffix works, unsubscribe from everything.
  $config
    ->set('subscription.use_combined', 'multiple');
  $config
    ->save();
  $edit = array(
    'mail[0][value]' => $mail,
  );
  foreach (array_keys($newsletters) as $newsletter_id) {
    $edit['subscriptions[' . $newsletter_id . ']'] = TRUE;
  }
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Unsubscribe'));
  $this
    ->assertText(t('You will receive a confirmation e-mail shortly containing further instructions on how to cancel your subscription.'));
  $confirm_url = $this
    ->extractConfirmationLink($this
    ->getMail(6));
  $this
    ->drupalGet($confirm_url);
  $this
    ->drupalGet($confirm_url . '/ok');
  $this
    ->assertRaw(t('Subscription changes confirmed for %user.', array(
    '%user' => $mail,
  )), t('Confirmation message displayed.'));

  // Verify subscription changes.
  $subscriber_storage
    ->resetCache();
  $subscription_manager
    ->reset();
  foreach (array_keys($newsletters) as $newsletter_id) {
    $this
      ->assertFalse($subscription_manager
      ->isSubscribed($mail, $newsletter_id));
  }

  // Call confirmation url after it is allready used.
  // Using direct url.
  $this
    ->drupalGet($confirm_url . '/ok');
  $this
    ->assertNoResponse(404, 'Redirected after calling confirmation url more than once.');
  $this
    ->assertRaw(t('All changes to your subscriptions where already applied. No changes made.'));

  // Using confirmation page.
  $this
    ->drupalGet($confirm_url);
  $this
    ->assertNoResponse(404, 'Redirected after calling confirmation url more than once.');
  $this
    ->assertRaw(t('All changes to your subscriptions where already applied. No changes made.'));

  // Test expired confirmation links.
  $enable = array_rand($newsletters, 3);
  $mail = $this
    ->randomEmail(8);
  $edit = array(
    'mail[0][value]' => $mail,
  );
  foreach ($enable as $newsletter_id) {
    $edit['subscriptions[' . $newsletter_id . ']'] = TRUE;
  }
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Subscribe'));
  $subscriber = simplenews_subscriber_load_by_mail($mail);
  $expired_timestamp = REQUEST_TIME - 86401;
  $changes = $subscriber
    ->getChanges();
  $hash = simplenews_generate_hash($subscriber
    ->getMail(), 'combined' . serialize($subscriber
    ->getChanges()), $expired_timestamp);
  $url = 'newsletter/confirm/combined/' . $subscriber
    ->id() . '/' . $expired_timestamp . '/' . $hash;
  $this
    ->drupalGet($url);
  $this
    ->assertText(t('This link has expired.'));
  $this
    ->drupalPostForm(NULL, array(), t('Request new confirmation mail'));
  $confirm_url = $this
    ->extractConfirmationLink($this
    ->getMail(8));

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    $this
      ->assertMailText(t('Subscribe to @name', array(
      '@name' => $newsletter->name,
    )), 8, in_array($newsletter_id, $enable));
  }
  $this
    ->drupalGet($confirm_url);
  $this
    ->assertRaw(t('Are you sure you want to confirm the following subscription changes for %user?', array(
    '%user' => simplenews_mask_mail($mail),
  )), t('Subscription confirmation found.'));

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    if (in_array($newsletter_id, $enable)) {
      $this
        ->assertText(t('Subscribe to @name', array(
        '@name' => $newsletter->name,
      )));
    }
    else {
      $this
        ->assertNoText(t('Subscribe to @name', array(
        '@name' => $newsletter->name,
      )));
    }
  }
  $this
    ->drupalPostForm($confirm_url, array(), t('Confirm'));
  $this
    ->assertRaw(t('Subscription changes confirmed for %user.', array(
    '%user' => $mail,
  )), t('Anonymous subscriber added to newsletter'));
}