text: define(['common/js/spec_helpers/template_helpers',
      'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
      'js/dashboard/donation'],
      function(TemplateHelpers, AjaxHelpers) {
          'use strict';
  
          describe('edx.dashboard.donation.DonationView', function() {
              var PAYMENT_URL = 'https://fake.processor.com/pay/';
              var PAYMENT_PARAMS = {
                  orderId: 'test-order',
                  signature: 'abcd1234'
              };
              var AMOUNT = '45.67';
              var COURSE_ID = 'edx/DemoX/Demo';
  
              var view = null;
              var requests = null;
  
              beforeEach(function() {
                  setFixtures('<div></div>');
                  TemplateHelpers.installTemplate('templates/dashboard/donation');
  
                  view = new edx.dashboard.donation.DonationView({
                      el: $('#jasmine-fixtures'),
                      course: COURSE_ID
                  }).render();
  
                  // Stub out the actual submission of the payment form
                  // (which would cause the page to reload)
                  // This function gets passed the dynamically constructed
                  // form with signed payment parameters from the LMS server,
                  // so we can verify that the form is constructed correctly.
                  spyOn(view, 'submitPaymentForm').and.callFake(function() {});
  
                  // Stub the analytics event tracker
                  window.analytics = jasmine.createSpyObj('analytics', ['track']);
              });
  
              it('processes a donation for a course', function() {
                  // Spy on AJAX requests
                  requests = AjaxHelpers.requests(this);
  
                  // Enter a donation amount and proceed to the payment page
                  view.$amount.val(AMOUNT);
                  view.donate();
  
                  // Verify that the client contacts the server to create
                  // the donation item in the shopping cart and receive
                  // the signed payment params.
                  AjaxHelpers.expectRequest(
                      requests, 'POST', '/shoppingcart/donation/',
                      $.param({amount: AMOUNT, course_id: COURSE_ID})
                  );
  
                  // Simulate a response from the server containing the signed
                  // parameters to send to the payment processor
                  AjaxHelpers.respondWithJson(requests, {
                      payment_url: PAYMENT_URL,
                      payment_params: PAYMENT_PARAMS
                  });
  
                  // Verify that the payment form has the payment parameters
                  // sent by the LMS server, and that it's targeted at the
                  // correct payment URL.
                  // We stub out the actual submission of the form to avoid
                  // leaving the current page during the test.
                  expect(view.submitPaymentForm).toHaveBeenCalled();
                  var form = view.submitPaymentForm.calls.mostRecent().args[0];
                  expect(form.serialize()).toEqual($.param(PAYMENT_PARAMS));
                  expect(form.attr('method')).toEqual('post');
                  expect(form.attr('action')).toEqual(PAYMENT_URL);
              });
  
              it('validates the donation amount', function() {
                  var assertValidAmount = function(amount, isValid) {
                      expect(view.validateAmount(amount)).toBe(isValid);
                  };
                  assertValidAmount('', false);
                  assertValidAmount('  ', false);
                  assertValidAmount('abc', false);
                  assertValidAmount('14.', false);
                  assertValidAmount('.1', false);
                  assertValidAmount('-1', false);
                  assertValidAmount('-1.00', false);
                  assertValidAmount('-', false);
                  assertValidAmount('0', false);
                  assertValidAmount('0.00', false);
                  assertValidAmount('00.00', false);
                  assertValidAmount('3', true);
                  assertValidAmount('12.34', true);
                  assertValidAmount('278', true);
                  assertValidAmount('278.91', true);
                  assertValidAmount('0.14', true);
              });
  
              it('displays validation errors', function() {
                  // Attempt to submit an invalid donation amount
                  view.$amount.val('');
                  view.donate();
  
                  // Verify that the amount field is marked as having a validation error
                  expect(view.$amount).toHaveClass('validation-error');
  
                  // Verify that the error message appears
                  expect(view.$errorMsg.text()).toEqual('Please enter a valid donation amount.');
  
                  // Expect that the submit button is re-enabled to allow users to submit again
                  expect(view.$submit).not.toHaveClass('disabled');
  
                  // Try again, this time submitting a valid amount
                  view.$amount.val(AMOUNT);
                  view.donate();
  
                  // Expect that the errors are cleared
                  expect(view.$errorMsg.text()).toEqual('');
  
                  // Expect that the submit button is disabled
                  expect(view.$submit).toHaveClass('disabled');
              });
  
              it('displays an error when the server cannot be contacted', function() {
                  // Spy on AJAX requests
                  requests = AjaxHelpers.requests(this);
  
                  // Simulate an error from the LMS servers
                  view.donate();
                  AjaxHelpers.respondWithError(requests);
  
                  // Expect that the error is displayed
                  expect(view.$errorMsg.text()).toEqual('Your donation could not be submitted.');
  
                  // Verify that the submit button is re-enabled
                  // so users can try again.
                  expect(view.$submit).not.toHaveClass('disabled');
              });
  
              it('disables the submit button once the user donates', function() {
                  // Before we submit, the button should be enabled
                  expect(view.$submit).not.toHaveClass('disabled');
  
                  // Simulate starting a donation
                  // Since we're not simulating the AJAX response, this will block
                  // in the state just after the user kicks off the donation process.
                  view.donate();
  
                  // Verify that the submit button is disabled
                  expect(view.$submit).toHaveClass('disabled');
              });
  
              it('sends an analytics event when the user submits a donation', function() {
                  // Simulate the submission to the payment processor
                  // We skip the intermediary steps here by passing in
                  // the payment url and parameters,
                  // which the view would ordinarily retrieve from the LMS server.
                  view.startPayment({
                      payment_url: PAYMENT_URL,
                      payment_params: PAYMENT_PARAMS
                  });
  
                  // Verify that the analytics event was fired
                  expect(window.analytics.track).toHaveBeenCalledWith(
                      'edx.bi.user.payment_processor.visited',
                      {
                          category: 'donations',
                          label: COURSE_ID
                      }
                  );
              });
          });
      }
  );
  