You are here

public function SimplenewsSubscribeTest::testSubscribeMultiple in Simplenews 8.2

Same name and namespace in other branches
  1. 3.x tests/src/Functional/SimplenewsSubscribeTest.php \Drupal\Tests\simplenews\Functional\SimplenewsSubscribeTest::testSubscribeMultiple()

Subscribe to multiple newsletters at the same time.

File

tests/src/Functional/SimplenewsSubscribeTest.php, line 22

Class

SimplenewsSubscribeTest
Un/subscription of anonymous and authenticated users.

Namespace

Drupal\Tests\simplenews\Functional

Code

public function testSubscribeMultiple() {
  $admin_user = $this
    ->drupalCreateUser([
    '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 = [
      '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 = [
    '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.'));

  // Verify listed changes.
  foreach ($newsletters as $newsletter_id => $newsletter) {
    $this
      ->assertMailText(t('Subscribe to @name', [
      '@name' => $newsletter->name,
    ]), 0, in_array($newsletter_id, $enable));
  }
  $mails = $this
    ->getMails();
  $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?', [
    '%user' => simplenews_mask_mail($mail),
  ]));

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

  /** @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
        ->assertEquals(1, count($subscription_newsletter));
    }
    else {
      $this
        ->assertFalse($is_subscribed);
      $this
        ->assertEquals(0, count($subscription_newsletter));
    }
  }

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

  // Unsubscribe from two of the three enabled newsletters.
  $disable = array_rand(array_flip($enable), 2);
  $edit = [
    '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.'));

  // 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', [
      '@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?', [
    '%user' => simplenews_mask_mail($mail),
  ]));

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

  // 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 = [
    '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 = [
    '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 = [
    '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.'));
  $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 = [
    '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.', [
    '%user' => $mail,
  ]));

  // 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
    ->assertSession()
    ->statusCodeNotEquals(404);
  $this
    ->assertRaw(t('All changes to your subscriptions where already applied. No changes made.'));

  // Using confirmation page.
  $this
    ->drupalGet($confirm_url);
  $this
    ->assertSession()
    ->statusCodeNotEquals(404);
  $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 = [
    'mail[0][value]' => $mail,
  ];
  foreach ($enable as $newsletter_id) {
    $edit['subscriptions[' . $newsletter_id . ']'] = TRUE;
  }
  $this
    ->drupalPostForm('newsletter/subscriptions', $edit, t('Subscribe'));
  $subscriber = Subscriber::loadByMail($mail);
  $expired_timestamp = REQUEST_TIME - 86401;
  $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, [], 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', [
      '@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?', [
    '%user' => simplenews_mask_mail($mail),
  ]));

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