recurly-8.x-1.x-dev/modules/recurlyjs/tests/src/FunctionalJavascript/RecurlyJsBillingFormTest.php

modules/recurlyjs/tests/src/FunctionalJavascript/RecurlyJsBillingFormTest.php
<?php

namespace Drupal\Tests\recurlyjs\FunctionalJavascript;

use Drupal\recurly_test_client\RecurlyMockClient;

/**
 * Tests for RecurlyJsBillingForm.
 *
 * The form itself is the same form used in RecurlyJsSubscribeForm so here we
 * only test the things specific to the billing form controller.
 *
 * @group recurly
 * @covers \Drupal\recurlyjs\Form\RecurlyJsUpdateBillingForm;
 */
class RecurlyJsBillingFormTest extends RecurlyJsWebDriverTestBase {

  /**
   * User can not access billing form without a locally stored recurly account.
   */
  public function testBillingFormAccess() {
    $account = $this->drupalCreateUser(['manage recurly subscription']);
    $this->drupalLogin($account);

    $this->drupalGet('/user/' . $account->id() . '/subscription/billing');
    $this->assertSession()->pageTextContains('You are not authorized to access this page');
  }

  /**
   * Test validation and submission of the billing info update form.
   */
  public function testBillingForm() {
    $account = $this->createUserWithSubscription();
    $this->drupalLogin($account);

    RecurlyMockClient::addResponse('GET', '/accounts/abcdef1234567890', 'accounts/show-200.xml');
    RecurlyMockClient::addResponse('GET', '/accounts/abcdef1234567890/subscriptions?per_page=200', 'subscriptions/index-200-single.xml');

    // Visit the page first with no valid response for the billing_info request
    // and verify the error is caught.
    $this->drupalGet('/user/' . $account->id() . '/subscription/billing');
    $this->assertSession()->pageTextContains('Unable to retrieve billing information');

    // Add a mock for the billing_info request and try again.
    RecurlyMockClient::addResponse('GET', '/accounts/abcdef1234567890/billing_info', 'billing_info/show-200.xml');
    $this->drupalGet('/user/' . $account->id() . '/subscription/billing');

    $this->assertSession()->pageTextNotContains('Unable to retrieve billing information');
    $this->assertSession()->pageTextContains('We currently have the following credit card on file');
    // Display data from the billing_info mock, and properly mask the CC number.
    $this->assertSession()->pageTextContains('Visa Exp: 01/2049');
    $this->assertSession()->pageTextContains('xxxxxxxxxxxx1111');

    // Test that form gets prepopulated with values from Recurly. Use input
    // element IDs instead of names because the form code strips the name
    // attribute per Recurly JS recommendations.
    $this->assertSession()->fieldValueEquals('edit-first-name', 'Larry');
    $this->assertSession()->fieldValueEquals('edit-last-name', 'David');
    $this->assertSession()->fieldValueEquals('edit-address1', '123 Pretty Pretty Good St.');
    $this->assertSession()->fieldValueEquals('edit-city', 'Los Angeles');
    $this->assertSession()->fieldValueEquals('edit-state', 'CA');
    $this->assertSession()->fieldValueEquals('edit-postal-code', '90210');

    // Make sure all the RecurlyJS iframes have a 'name' attribute. They don't
    // by default, and we need one to be able to switch to the frame. So we use
    // the CSS class of the parent element.
    $javascript = "document.querySelectorAll('iframe').forEach(function(f) { f.setAttribute('name', f.parentElement.classList[f.parentElement.classList.length -1]); })";
    $this->getSession()->executeScript($javascript);

    // Try an invalid CC and ensure validation works.
    //
    // This also validates that the Recurly JS CC#, CVV, Month, and Year fields
    // get added to the page.
    $this->getSession()->switchToIFrame('recurly-hosted-field-number');
    $this->getSession()->getPage()->fillField('recurly-hosted-field-input', '4222222222222222');

    $this->getSession()->switchToWindow();
    $this->getSession()->switchToIFrame('recurly-hosted-field-cvv');
    $this->getSession()->getPage()->fillField('recurly-hosted-field-input', '666');

    $this->getSession()->switchToWindow();
    $this->getSession()->switchToIFrame('recurly-hosted-field-month');
    $this->getSession()->getPage()->fillField('recurly-hosted-field-input', '03');

    $this->getSession()->switchToWindow();
    $this->getSession()->switchToIFrame('recurly-hosted-field-year');
    $this->getSession()->getPage()->fillField('recurly-hosted-field-input', '2030');

    // Switch back to the main frame. And submit the invalid data.
    $this->getSession()->switchToWindow();
    $this->getSession()->getPage()->pressButton('Update');

    $this->assertSession()->pageTextContains('There was an error validating your request');
    $this->assertSession()->elementTextContains('css', '#recurly-form-errors', 'Credit Card number');

    // Switch to a known good CC number.
    $this->getSession()->switchToIFrame('recurly-hosted-field-number');
    $this->getSession()->getPage()->fillField('recurly-hosted-field-input', '4111111111111111');
    $this->getSession()->switchToWindow();

    // Tests for logic in
    // \Drupal\recurlyjs\Form\RecurlyJsUpdateBillingForm::submitForm().
    // First, invalid token, should return an \Recurly_NotFoundError.
    $this->removeJsFromForm();
    $this->submitForm([], 'Update');
    $this->assertSession()->pageTextContains('Could not find account or token is invalid or expired');

    // Then, if Recurly returns a validation error, we should get a
    // \Recurly_ValidationError.
    RecurlyMockClient::addResponse('PUT', '/accounts/abcdef1234567890/billing_info', 'billing_info/verify-422.xml');
    $this->removeJsFromForm();
    $this->submitForm([], 'Update');
    // Text comes from the mock error response.
    $this->assertSession()->pageTextContains('Only stored credit card billing information can be verified at this time');

    // And, if we just get some other random error from Recurly that should
    // result in an \Recurly_Error.
    RecurlyMockClient::addResponse('PUT', '/accounts/abcdef1234567890/billing_info', 'client/server-error-500.xml');
    $this->removeJsFromForm();
    $this->submitForm([], 'Update');
    // Text comes from the mock error response.
    $this->assertSession()->pageTextContains('An error occured while trying to update your account. Please contact a site administrator');
  }

  /**
   * Helper method to undbind Recurly JS from billing form.
   *
   * Normally this form needs to call recurly.token(), RecurlyJS does it's work
   * and sets the recurly-token field value. And then the form, without all the
   * CC details, is submitted to Drupal. For testing, we can bypass the Recurly
   * JS API by un-binding the JS callback and spoofing the recurly-token value.
   */
  protected function removeJsFromForm() {
    $this->getSession()->executeScript("document.querySelectorAll('.recurly-form-wrapper form').forEach(function(el) { el.removeEventListener('submit', Drupal.recurly.recurlyJSTokenFormSubmit); });");
    $this->getSession()->executeScript("document.querySelector('[name=\"recurly-token\"]').value = '1234-asdf'");
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc