<commit_before>exports.config = {
    // =================
    // Service Providers
    // =================
    // WebdriverIO supports Sauce Labs, Browserstack, and Testing Bot (other cloud providers
    // should work too though). These services define specific user and key (or access key)
    // values you need to put in here in order to connect to these services.
    //
    user: process.env.SAUCE_USERNAME,
    key: process.env.SAUCE_ACCESS_KEY,
    //
    // ==================
    // Specify Test Files
    // ==================
    // Define which test specs should run. The pattern is relative to the directory
    // from which `wdio` was called. Notice that, if you are calling `wdio` from an
    // NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
    // directory is where your package.json resides, so `wdio` will be called from there.
    //
    specs: [
        './test/specs/**/*.js'
    ],
    // Patterns to exclude.
    exclude: [
        // 'path/to/excluded/files'
    ],
    //
    // ============
    // Capabilities
    // ============
    // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
    // time. Depending on the number of capabilities, WebdriverIO launches several test
    // sessions. Within your capabilities you can overwrite the spec and exclude options in
    // order to group specific specs to a specific capability.
    //
    // First, you can define how many instances should be started at the same time. Let's
    // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
    // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
    // files and you set maxInstances to 10, all spec files will get tested at the same time
    // and 30 processes will get spawned. The property handles how many capabilities
    // from the same test should run tests.
    //
    maxInstances: 10,
    //
    // If you have trouble getting all important capabilities together, check out the
    // Sauce Labs platform configurator - a great tool to configure your capabilities:
    // https://docs.saucelabs.com/reference/platforms-configurator
    //
    capabilities: [{
        // maxInstances can get overwritten per capability. So if you have an in-house Selenium
        // grid with only 5 firefox instances available you can make sure that not more than
        // 5 instances get started at a time.
        maxInstances: 5,
        //
        browserName: 'firefox'
    }],
    //
    // ===================
    // Test Configurations
    // ===================
    // Define all options that are relevant for the WebdriverIO instance here
    //
    // By default WebdriverIO commands are executed in a synchronous way using
    // the wdio-sync package. If you still want to run your tests in an async way
    // e.g. using promises you can set the sync option to false.
    sync: true,
    //
    // Level of logging verbosity: silent | verbose | command | data | result | error
    logLevel: 'silent',
    //
    // Enables colors for log output.
    coloredLogs: true,
    //
    // If you only want to run your tests until a specific amount of tests have failed use
    // bail (default is 0 - don't bail, run all tests).
    bail: 0,
    //
    // Saves a screenshot to a given path if a command fails.
    screenshotPath: './errorShots/',
    //
    // Set a base URL in order to shorten url command calls. If your url parameter starts
    // with "/", then the base url gets prepended.
    baseUrl: 'http://the-internet.herokuapp.com',
    //
    // Default timeout for all waitFor* commands.
    waitforTimeout: 10000,
    //
    // Default timeout in milliseconds for request
    // if Selenium Grid doesn't send response
    connectionRetryTimeout: 90000,
    //
    // Default request retries count
    connectionRetryCount: 3,
    //
    // Initialize the browser instance with a WebdriverIO plugin. The object should have the
    // plugin name as key and the desired plugin options as properties. Make sure you have
    // the plugin installed before running any tests. The following plugins are currently
    // available:
    // WebdriverCSS: https://github.com/webdriverio/webdrivercss
    // WebdriverRTC: https://github.com/webdriverio/webdriverrtc
    // Browserevent: https://github.com/webdriverio/browserevent
    // plugins: {
    //     webdrivercss: {
    //         screenshotRoot: 'my-shots',
    //         failedComparisonsRoot: 'diffs',
    //         misMatchTolerance: 0.05,
    //         screenWidth: [320,480,640,1024]
    //     },
    //     webdriverrtc: {},
    //     browserevent: {}
    // },
    //
    // Test runner services
    // Services take over a specific job you don't want to take care of. They enhance
    // your test setup with almost no effort. Unlike plugins, they don't add new
    // commands. Instead, they hook themselves up into the test process.
    services: ['sauce'],
    //
    // Framework you want to run your specs with.
    // The following are supported: Mocha, Jasmine, and Cucumber
    // see also: http://webdriver.io/guide/testrunner/frameworks.html
    //
    // Make sure you have the wdio adapter package for the specific framework installed
    // before running any tests.
    framework: 'jasmine',
    //
    // Test reporter for stdout.
    // The only one supported by default is 'dot'
    // see also: http://webdriver.io/guide/testrunner/reporters.html
    reporters: ['spec'],

    //
    // Options to be passed to Jasmine.
    jasmineNodeOpts: {
        //
        // Jasmine default timeout
        defaultTimeoutInterval: 30000
    },
    //
    // =====
    // Hooks
    // =====
    // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
    // it and to build services around it. You can either apply a single function or an array of
    // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
    // resolved to continue.
    /**
     * Gets executed once before all workers get launched.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     */
    // onPrepare: function (config, capabilities) {
    // },
    /**
     * Gets executed just before initialising the webdriver session and test framework. It allows you
     * to manipulate configurations depending on the capability or spec.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    beforeSession: function (config, capabilities, specs) {
        require('babel-register')
    }
    /**
     * Gets executed before test execution begins. At this point you can access to all global
     * variables like `browser`. It is the perfect place to define custom commands.
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    // before: function (capabilities, specs) {
    // },
    //
    /**
     * Hook that gets executed before the suite starts
     * @param {Object} suite suite details
     */
    // beforeSuite: function (suite) {
    // },
    /**
     * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
     * beforeEach in Mocha)
     */
    // beforeHook: function () {
    // },
    /**
     * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
     * afterEach in Mocha)
     */
    // afterHook: function () {
    // },
    /**
     * Function to be executed before a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
     * @param {Object} test test details
     */
    // beforeTest: function (test) {
    // },
    /**
     * Runs before a WebdriverIO command gets executed.
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     */
    // beforeCommand: function (commandName, args) {
    // },
    /**
     * Runs after a WebdriverIO command gets executed
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     * @param {Number} result 0 - command success, 1 - command error
     * @param {Object} error error object if any
     */
    // afterCommand: function (commandName, args, result, error) {
    // },
    /**
     * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
     * @param {Object} test test details
     */
    // afterTest: function (test) {
    // },
    /**
     * Hook that gets executed after the suite has ended
     * @param {Object} suite suite details
     */
    // afterSuite: function (suite) {
    // },
    /**
     * Gets executed after all tests are done. You still have access to all global variables from
     * the test.
     * @param {Number} result 0 - test pass, 1 - test fail
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // after: function (result, capabilities, specs) {
    // },
    /**
     * Gets executed right after terminating the webdriver session.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // afterSession: function (config, capabilities, specs) {
    // },
    /**
     * Gets executed after all workers got shut down and the process is about to exit. It is not
     * possible to defer the end of the process using a promise.
     * @param {Object} exitCode 0 - success, 1 - fail
     */
    // onComplete: function(exitCode) {
    // }
}
<commit_msg>add build number<commit_after>exports.config = {
    // =================
    // Service Providers
    // =================
    // WebdriverIO supports Sauce Labs, Browserstack, and Testing Bot (other cloud providers
    // should work too though). These services define specific user and key (or access key)
    // values you need to put in here in order to connect to these services.
    //
    user: process.env.SAUCE_USERNAME,
    key: process.env.SAUCE_ACCESS_KEY,
    //
    // ==================
    // Specify Test Files
    // ==================
    // Define which test specs should run. The pattern is relative to the directory
    // from which `wdio` was called. Notice that, if you are calling `wdio` from an
    // NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
    // directory is where your package.json resides, so `wdio` will be called from there.
    //
    specs: [
        './test/specs/**/*.js'
    ],
    // Patterns to exclude.
    exclude: [
        // 'path/to/excluded/files'
    ],
    //
    // ============
    // Capabilities
    // ============
    // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
    // time. Depending on the number of capabilities, WebdriverIO launches several test
    // sessions. Within your capabilities you can overwrite the spec and exclude options in
    // order to group specific specs to a specific capability.
    //
    // First, you can define how many instances should be started at the same time. Let's
    // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
    // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
    // files and you set maxInstances to 10, all spec files will get tested at the same time
    // and 30 processes will get spawned. The property handles how many capabilities
    // from the same test should run tests.
    //
    maxInstances: 10,
    //
    // If you have trouble getting all important capabilities together, check out the
    // Sauce Labs platform configurator - a great tool to configure your capabilities:
    // https://docs.saucelabs.com/reference/platforms-configurator
    //
    capabilities: [{
        // maxInstances can get overwritten per capability. So if you have an in-house Selenium
        // grid with only 5 firefox instances available you can make sure that not more than
        // 5 instances get started at a time.
        maxInstances: 5,
        //
        browserName: 'firefox',
        build: process.env.TRAVIS_BUILD_NUMBER
    }],
    //
    // ===================
    // Test Configurations
    // ===================
    // Define all options that are relevant for the WebdriverIO instance here
    //
    // By default WebdriverIO commands are executed in a synchronous way using
    // the wdio-sync package. If you still want to run your tests in an async way
    // e.g. using promises you can set the sync option to false.
    sync: true,
    //
    // Level of logging verbosity: silent | verbose | command | data | result | error
    logLevel: 'silent',
    //
    // Enables colors for log output.
    coloredLogs: true,
    //
    // If you only want to run your tests until a specific amount of tests have failed use
    // bail (default is 0 - don't bail, run all tests).
    bail: 0,
    //
    // Saves a screenshot to a given path if a command fails.
    screenshotPath: './errorShots/',
    //
    // Set a base URL in order to shorten url command calls. If your url parameter starts
    // with "/", then the base url gets prepended.
    baseUrl: 'http://the-internet.herokuapp.com',
    //
    // Default timeout for all waitFor* commands.
    waitforTimeout: 10000,
    //
    // Default timeout in milliseconds for request
    // if Selenium Grid doesn't send response
    connectionRetryTimeout: 90000,
    //
    // Default request retries count
    connectionRetryCount: 3,
    //
    // Initialize the browser instance with a WebdriverIO plugin. The object should have the
    // plugin name as key and the desired plugin options as properties. Make sure you have
    // the plugin installed before running any tests. The following plugins are currently
    // available:
    // WebdriverCSS: https://github.com/webdriverio/webdrivercss
    // WebdriverRTC: https://github.com/webdriverio/webdriverrtc
    // Browserevent: https://github.com/webdriverio/browserevent
    // plugins: {
    //     webdrivercss: {
    //         screenshotRoot: 'my-shots',
    //         failedComparisonsRoot: 'diffs',
    //         misMatchTolerance: 0.05,
    //         screenWidth: [320,480,640,1024]
    //     },
    //     webdriverrtc: {},
    //     browserevent: {}
    // },
    //
    // Test runner services
    // Services take over a specific job you don't want to take care of. They enhance
    // your test setup with almost no effort. Unlike plugins, they don't add new
    // commands. Instead, they hook themselves up into the test process.
    services: ['sauce'],
    //
    // Framework you want to run your specs with.
    // The following are supported: Mocha, Jasmine, and Cucumber
    // see also: http://webdriver.io/guide/testrunner/frameworks.html
    //
    // Make sure you have the wdio adapter package for the specific framework installed
    // before running any tests.
    framework: 'jasmine',
    //
    // Test reporter for stdout.
    // The only one supported by default is 'dot'
    // see also: http://webdriver.io/guide/testrunner/reporters.html
    reporters: ['spec'],

    //
    // Options to be passed to Jasmine.
    jasmineNodeOpts: {
        //
        // Jasmine default timeout
        defaultTimeoutInterval: 30000
    },
    //
    // =====
    // Hooks
    // =====
    // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
    // it and to build services around it. You can either apply a single function or an array of
    // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
    // resolved to continue.
    /**
     * Gets executed once before all workers get launched.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     */
    // onPrepare: function (config, capabilities) {
    // },
    /**
     * Gets executed just before initialising the webdriver session and test framework. It allows you
     * to manipulate configurations depending on the capability or spec.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    beforeSession: function (config, capabilities, specs) {
        require('babel-register')
    }
    /**
     * Gets executed before test execution begins. At this point you can access to all global
     * variables like `browser`. It is the perfect place to define custom commands.
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that are to be run
     */
    // before: function (capabilities, specs) {
    // },
    //
    /**
     * Hook that gets executed before the suite starts
     * @param {Object} suite suite details
     */
    // beforeSuite: function (suite) {
    // },
    /**
     * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
     * beforeEach in Mocha)
     */
    // beforeHook: function () {
    // },
    /**
     * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
     * afterEach in Mocha)
     */
    // afterHook: function () {
    // },
    /**
     * Function to be executed before a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
     * @param {Object} test test details
     */
    // beforeTest: function (test) {
    // },
    /**
     * Runs before a WebdriverIO command gets executed.
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     */
    // beforeCommand: function (commandName, args) {
    // },
    /**
     * Runs after a WebdriverIO command gets executed
     * @param {String} commandName hook command name
     * @param {Array} args arguments that command would receive
     * @param {Number} result 0 - command success, 1 - command error
     * @param {Object} error error object if any
     */
    // afterCommand: function (commandName, args, result, error) {
    // },
    /**
     * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
     * @param {Object} test test details
     */
    // afterTest: function (test) {
    // },
    /**
     * Hook that gets executed after the suite has ended
     * @param {Object} suite suite details
     */
    // afterSuite: function (suite) {
    // },
    /**
     * Gets executed after all tests are done. You still have access to all global variables from
     * the test.
     * @param {Number} result 0 - test pass, 1 - test fail
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // after: function (result, capabilities, specs) {
    // },
    /**
     * Gets executed right after terminating the webdriver session.
     * @param {Object} config wdio configuration object
     * @param {Array.<Object>} capabilities list of capabilities details
     * @param {Array.<String>} specs List of spec file paths that ran
     */
    // afterSession: function (config, capabilities, specs) {
    // },
    /**
     * Gets executed after all workers got shut down and the process is about to exit. It is not
     * possible to defer the end of the process using a promise.
     * @param {Object} exitCode 0 - success, 1 - fail
     */
    // onComplete: function(exitCode) {
    // }
}
<|endoftext|>


<commit_before>'use strict';
/* jshint node: true */
/* jshint esnext: true */
/* global describe, beforeEach, beforeAll, afterAll, spyOn, it, expect, fail */

describe('registration', () => {

  const registration = require('../../service/registration');
  const participants = require('../../service/participants');
  const tshirts = require('../../service/tshirts');
  const participant = require('../../domain/participant');

  const mails = require('../../service/util/mails');
  const helper = require('../journeyHelper');

  let originalRegistrationStatus;
  let startNr = 30;

  const aParticipant = participant.from({
    firstname: 'Hertha',
    lastname: 'Mustermann',
    email: 'h.mustermann@example.com',
    category: 'Unicorn',
    birthyear: 1980,
    visibility: 'yes',
    discount: 'no',
    team: 'Crazy runners'
  }).withSecureId('some_secure_id');

  beforeAll((done) => {
    registration.isClosed().then(isClosed => {
      originalRegistrationStatus = isClosed;
      if (isClosed) {
        registration.reopen().then(() => {
          done();
        });
      } else {
        done();
      }
    });
  });

  afterAll((done) => {
    if (!originalRegistrationStatus) {
      registration.reopen().then(() => {
        helper.closeDbConnection(done);
      });
    } else {
      helper.closeDbConnection(done);
    }
  });

  describe('start()', () => {
    it('should save the participant and send confirmation email', (done) => {
      spyOn(participants, 'save').and.callThrough();
      spyOn(participants, 'markPayed').and.callThrough();
      spyOn(mails, 'sendEmail');
      spyOn(tshirts, 'addFor');

      const p = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        category: 'Unicorn',
        birthyear: 1980,
        visibility: 'yes',
        discount: 'no',
        team: 'Crazy runners'
      });

      registration.start(p)
        .then((result) => {
          expect(participants.save).toHaveBeenCalled();

          let participant = participants.save.calls.mostRecent().args[0];
          expect(participant.firstname).toBe(p.firstname);
          expect(participant.paymentToken).toBe(result.token);
          expect(participant.secureID).toBe(result.secureid);
          expect(participant.start_number).toBe(result.startnr);

          expect(participants.markPayed).not.toHaveBeenCalled();

          expect(mails.sendEmail).toHaveBeenCalled();

          let participantsEmail = mails.sendEmail.calls.mostRecent().args[0];
          expect(participantsEmail).toBe(p.email);

          let subject = mails.sendEmail.calls.mostRecent().args[1];
          expect(subject).toBe('Lauf Gegen Rechts: Registrierung erfolgreich');

          let content = mails.sendEmail.calls.mostRecent().args[2];
          expect(content).toMatch(/Danke/);
          expect(content).toMatch(/Bitte überweise den Betrag/);

          expect(tshirts.addFor).not.toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });

    it('should mark the participant as payed if their amount is 0 and send the matching email', (done) => {
      spyOn(participants, 'save').and.callThrough();
      spyOn(participants, 'markPayed').and.callThrough();
      spyOn(mails, 'sendEmail');
      spyOn(tshirts, 'addFor');

      const p = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        category: 'Unicorn',
        birthyear: 1980,
        visibility: 'yes',
        discount: 'free',
        couponcode: 'Free2016',
        team: 'Crazy runners'
      });

      registration.start(p)
        .then((result) => {
          expect(participants.save).toHaveBeenCalled();

          let participant = participants.save.calls.mostRecent().args[0];
          expect(participant.firstname).toBe(p.firstname);
          expect(participant.paymentToken).toBe(result.token);
          expect(participant.secureID).toBe(result.secureid);
          expect(participant.start_number).toBe(result.startnr);

          expect(participants.markPayed).toHaveBeenCalled();

          expect(mails.sendEmail).toHaveBeenCalled();

          let participantsEmail = mails.sendEmail.calls.mostRecent().args[0];
          expect(participantsEmail).toBe(p.email);

          let subject = mails.sendEmail.calls.mostRecent().args[1];
          expect(subject).toBe('Lauf Gegen Rechts: Registrierung erfolgreich');

          let content = mails.sendEmail.calls.mostRecent().args[2];
          expect(content).toMatch(/Danke/);
          expect(content).not.toMatch(/Bitte überweise den Betrag/);

          expect(tshirts.addFor).not.toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });

    it('should call addFor if one ordered', (done) => {
      spyOn(tshirts, 'addFor');

      const pWithShirt = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        birthyear: 1980,
        category: 'Horse',
        visibility: 'yes',
        discount: 'no',
        shirt: 'yes',
        size: 'XS',
        model: 'Crazy cool fit'
      });

      registration.start(pWithShirt)
        .then(() => {
          expect(tshirts.addFor).toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });
  });

  describe('confirm()', () => {
    it('should mark the participant as payed and send a confirmation mail which includes the edit link', (done) => {
      spyOn(participants, 'markPayed').and.callThrough();
      spyOn(mails, 'sendEmail');

      participants.save(aParticipant.withToken('token x').withStartNr(startNr++))
        .then(function (participantId) {
          registration.confirm(participantId)
            .then(() => {
              expect(participants.markPayed).toHaveBeenCalledWith(participantId);

              expect(mails.sendEmail).toHaveBeenCalled();
              let partcipantsEmail = mails.sendEmail.calls.mostRecent().args[0];
              expect(partcipantsEmail).toBe(aParticipant.email);
              let subject = mails.sendEmail.calls.mostRecent().args[1];
              expect(subject).toBe('Lauf gegen Rechts: Zahlung erhalten');
              let content = mails.sendEmail.calls.mostRecent().args[2];
              expect(content).toMatch(aParticipant.firstname);
              expect(content).toMatch(/eingegangen/);
              expect(content).toMatch('some_secure_id');

              done();
            })
            .fail(fail);
        }).fail(fail);
    });

    it('should give error if ID is invalid', (done) => {
      let wrongId = '999';

      participants.save(aParticipant.withToken('token y').withStartNr(startNr++))
        .then(() => {
          registration.confirm(wrongId)
            .catch(() => {
              done();
            });
        }).fail(fail);
    });
  });

  it('should close the registration', (done) => {
    registration.close()
      .then(() => {
        registration.isClosed()
          .then((isClosed) => {
            expect(isClosed).toEqual(true);
            done();
          })
          .fail(fail);
      })
      .fail(fail);
  });
});
<commit_msg>added new IT for couponcode and tshirt<commit_after>'use strict';
/* jshint node: true */
/* jshint esnext: true */
/* global describe, beforeEach, beforeAll, afterAll, spyOn, it, expect, fail */

describe('registration', () => {

  const registration = require('../../service/registration');
  const participants = require('../../service/participants');
  const tshirts = require('../../service/tshirts');
  const participant = require('../../domain/participant');

  const mails = require('../../service/util/mails');
  const helper = require('../journeyHelper');

  let originalRegistrationStatus;
  let startNr = 30;

  const aParticipant = participant.from({
    firstname: 'Hertha',
    lastname: 'Mustermann',
    email: 'h.mustermann@example.com',
    category: 'Unicorn',
    birthyear: 1980,
    visibility: 'yes',
    discount: 'no',
    team: 'Crazy runners'
  }).withSecureId('some_secure_id');

  beforeAll((done) => {
    registration.isClosed().then(isClosed => {
      originalRegistrationStatus = isClosed;
      if (isClosed) {
        registration.reopen().then(() => {
          done();
        });
      } else {
        done();
      }
    });
  });

  afterAll((done) => {
    if (!originalRegistrationStatus) {
      registration.reopen().then(() => {
        helper.closeDbConnection(done);
      });
    } else {
      helper.closeDbConnection(done);
    }
  });

  describe('start()', () => {
    it('should save the participant and send confirmation email', (done) => {
      spyOn(participants, 'save').and.callThrough();
      spyOn(participants, 'markPayed').and.callThrough();
      spyOn(mails, 'sendEmail');
      spyOn(tshirts, 'addFor');

      const p = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        category: 'Unicorn',
        birthyear: 1980,
        visibility: 'yes',
        discount: 'no',
        team: 'Crazy runners'
      });

      registration.start(p)
        .then((result) => {
          expect(participants.save).toHaveBeenCalled();

          let participant = participants.save.calls.mostRecent().args[0];
          expect(participant.firstname).toBe(p.firstname);
          expect(participant.paymentToken).toBe(result.token);
          expect(participant.secureID).toBe(result.secureid);
          expect(participant.start_number).toBe(result.startnr);

          expect(participants.markPayed).not.toHaveBeenCalled();

          expect(mails.sendEmail).toHaveBeenCalled();

          let participantsEmail = mails.sendEmail.calls.mostRecent().args[0];
          expect(participantsEmail).toBe(p.email);

          let subject = mails.sendEmail.calls.mostRecent().args[1];
          expect(subject).toBe('Lauf Gegen Rechts: Registrierung erfolgreich');

          let content = mails.sendEmail.calls.mostRecent().args[2];
          expect(content).toMatch(/Danke/);
          expect(content).toMatch(/Bitte überweise den Betrag/);

          expect(tshirts.addFor).not.toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });

    it('should mark the participant as payed if their amount is 0 and send the matching email', (done) => {
      spyOn(participants, 'save').and.callThrough();
      spyOn(participants, 'markPayed').and.callThrough();
      spyOn(mails, 'sendEmail');
      spyOn(tshirts, 'addFor');

      const p = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        category: 'Unicorn',
        birthyear: 1980,
        visibility: 'yes',
        discount: 'free',
        couponcode: 'Free2016',
        team: 'Crazy runners'
      });

      registration.start(p)
        .then((result) => {
          expect(participants.save).toHaveBeenCalled();

          let participant = participants.save.calls.mostRecent().args[0];
          expect(participant.firstname).toBe(p.firstname);
          expect(participant.paymentToken).toBe(result.token);
          expect(participant.secureID).toBe(result.secureid);
          expect(participant.start_number).toBe(result.startnr);

          expect(participants.markPayed).toHaveBeenCalled();

          expect(mails.sendEmail).toHaveBeenCalled();

          let participantsEmail = mails.sendEmail.calls.mostRecent().args[0];
          expect(participantsEmail).toBe(p.email);

          let subject = mails.sendEmail.calls.mostRecent().args[1];
          expect(subject).toBe('Lauf Gegen Rechts: Registrierung erfolgreich');

          let content = mails.sendEmail.calls.mostRecent().args[2];
          expect(content).toMatch(/Danke/);
          expect(content).not.toMatch(/Bitte überweise den Betrag/);

          expect(tshirts.addFor).not.toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });

    it('should call addFor if one ordered', (done) => {
      spyOn(tshirts, 'addFor');

      const pWithShirt = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        birthyear: 1980,
        category: 'Horse',
        visibility: 'yes',
        discount: 'no',
        shirt: 'yes',
        size: 'XS',
        model: 'Crazy cool fit'
      });

      registration.start(pWithShirt)
        .then(() => {
          expect(tshirts.addFor).toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });

    it('should not mark as payed if coupon user ordered a shirt', (done) => {
      spyOn(tshirts, 'addFor');
      spyOn(participants, 'markPayed');

      const pWithShirt = participant.from({
        firstname: 'Hertha',
        lastname: 'Mustermann',
        email: 'h.mustermann@example.com',
        birthyear: 1980,
        category: 'Horse',
        visibility: 'yes',
        discount: 'free',
        couponcode: 'Free2016',
        shirt: 'yes',
        size: 'XS',
        model: 'Crazy cool fit'
      });

      registration.start(pWithShirt)
        .then(() => {
          expect(participants.markPayed).not.toHaveBeenCalled();
          expect(tshirts.addFor).toHaveBeenCalled();
          done();
        })
        .fail(fail);
    });
  });

  describe('confirm()', () => {
    it('should mark the participant as payed and send a confirmation mail which includes the edit link', (done) => {
      spyOn(participants, 'markPayed').and.callThrough();
      spyOn(mails, 'sendEmail');

      participants.save(aParticipant.withToken('token x').withStartNr(startNr++))
        .then(function (participantId) {
          registration.confirm(participantId)
            .then(() => {
              expect(participants.markPayed).toHaveBeenCalledWith(participantId);

              expect(mails.sendEmail).toHaveBeenCalled();
              let partcipantsEmail = mails.sendEmail.calls.mostRecent().args[0];
              expect(partcipantsEmail).toBe(aParticipant.email);
              let subject = mails.sendEmail.calls.mostRecent().args[1];
              expect(subject).toBe('Lauf gegen Rechts: Zahlung erhalten');
              let content = mails.sendEmail.calls.mostRecent().args[2];
              expect(content).toMatch(aParticipant.firstname);
              expect(content).toMatch(/eingegangen/);
              expect(content).toMatch('some_secure_id');

              done();
            })
            .fail(fail);
        }).fail(fail);
    });

    it('should give error if ID is invalid', (done) => {
      let wrongId = '999';

      participants.save(aParticipant.withToken('token y').withStartNr(startNr++))
        .then(() => {
          registration.confirm(wrongId)
            .catch(() => {
              done();
            });
        }).fail(fail);
    });
  });

  it('should close the registration', (done) => {
    registration.close()
      .then(() => {
        registration.isClosed()
          .then((isClosed) => {
            expect(isClosed).toEqual(true);
            done();
          })
          .fail(fail);
      })
      .fail(fail);
  });
});
<|endoftext|>


<commit_before>'use strict';

var debug = require('debug')('mj:create');
var format = require('util').format;
var Khaos = require('khaos');
var path = require('path');
var fs = require('fs');

var executor = require('../util/executor');

var TEMPLATES = ['empty', /* 'cli', 'view', 'spa', 'full', 'util', 'doc' */];

module.exports = function(args, done) {

  var tasks = {
    /**
     * make sure the template exists.
     */

    'template': function (callback) {
      if (TEMPLATES.indexOf(args['<template>']) === -1) {
        return callback(new Error(format('Unknown template "%s". Run `mj help create` for list of valid templates.', args['<template>'])));
      }
      var khaos = new Khaos(path.join(__dirname, '../templates/', args['<template>']));

      // return khaos instance in results
      return callback(null, khaos);
    },

    /**
     * before copying, make sure the target directory is empty or does not exist.
     */
    'destination': function(callback) {
      fs.readdir(args['<directory>'], function (err, files) {
        // error here means it does not exist, which is good.
        if (err) return callback(null, args['<directory>']);
        if ((files.length) > 0) return callback(new Error(format('destination directory %s is not empty.', path.resolve(args['<directory>']))));
        return callback(null, args['<directory>']);
      });
    },

    /**
     * now copy template to destination with khaos, prompt for handlebar variables
     */
    'copy': [
      'template',
      'destination',
      function(callback, results) {
        var khaos = results.template;
        khaos.generate(results.destination, callback);
      }
    ]
  };

  var options = {
    name: 'create',  // this name is used when --verbose is not set
    verbose: args['--verbose'],  // set verbosity or pass through from cli
    spinner: false, // turn off spinner because of khaos prompts
    success: format('new project with template "%s" created.', args['<template>'])
  };

  executor(tasks, options, done);
};
<commit_msg>template dependency tree implemented.<commit_after>'use strict';

var debug = require('debug')('mj:create');
var format = require('util').format;
var Khaos = require('khaos');
var path = require('path');
var fs = require('fs');
var executor = require('../util/executor');

// Template dependency tree
var templateDeps = {
  empty: null,
  cli: 'empty',
  view: 'empty',
  util: 'empty',
  doc: 'empty',
  spa: 'view',
  full: 'spa'
};

module.exports = function(args, done) {

  var tasks = {
    /**
     * make sure the template exists.
     */
    'template': function (callback) {
      if (Object.keys(templateDeps).indexOf(args['<template>']) === -1) {
        return callback(new Error(format('Unknown template "%s". Run ' +
          '`mj help create` for list of valid templates.', args['<template>'])));
      }
      return callback(null);
    },

    /**
     * before copying, make sure the target directory is empty or does not exist.
     */
    'destination': function(callback) {
      fs.readdir(args['<directory>'], function (err, files) {
        // error here means it does not exist, which is good.
        if (err) return callback(null, args['<directory>']);
        if ((files.length) > 0) return callback(new Error(format('destination ' +
          'directory %s is not empty.', path.resolve(args['<directory>']))));
        return callback(null, args['<directory>']);
      });
    }
  };

  // add khaos.generate tasks for each template in the dependency tree
  var generateTemplate = function (template) {
    return function (callback, results) {
      var khaos = new Khaos(path.join(__dirname, '../templates/', template));
      khaos.generate(results.destination, callback);
    };
  };
  var curr = args['<template>'];
  while (curr) {
    var parent = templateDeps[curr];
    // non-root depends on parent template, root on 'template' and 'destination'
    tasks[curr] = parent ?
      [parent, generateTemplate(curr)] :
      ['template', 'destination', generateTemplate(curr)];
    curr = parent;
  }

  var options = {
    name: 'create',  // this name is used when --verbose is not set
    verbose: args['--verbose'],  // set verbosity or pass through from cli
    spinner: false, // turn off spinner because of khaos prompts
    success: format('new project with template "%s" created.', args['<template>'])
  };

  executor(tasks, options, done);
};
<|endoftext|>


<commit_before>/*eslint quote-props: [2, "always"] */

'use strict';

// ESLint Configuration Files enables to include comments.
// http://eslint.org/docs/configuring/#comments-in-configuration-files
module.exports = {
    'parserOptions': {
        'ecmaVersion': 5,
    },

    'env': {
        'node': true,
    },

    'rules': {
        'no-var': 0,
    }
};
<commit_msg>refactor(eslint): use 'commonjs' env instead of 'node'.<commit_after>/*eslint quote-props: [2, "always"] */

'use strict';

// ESLint Configuration Files enables to include comments.
// http://eslint.org/docs/configuring/#comments-in-configuration-files
module.exports = {
    'parserOptions': {
        'ecmaVersion': 5,
    },

    'env': {
        'es6': false,
        'node': false,
        'commonjs': true,
    },

    'rules': {
        'no-var': 0,
    }
};
<|endoftext|>


<commit_before>(function (window, undefined) {

    var TIMEOUT = 60000;

    // don't break if there's no console
    if (typeof (window.console) === "undefined") {
        window.console = { log: function () { }, dir: function () { } };
    }

    // PollDance.Request has on('finished', int code, object result, object headers) and on('error', int reason) callback members

    var JsonCallbacks = {
        id: 0,
        requests: {},
        emptyCallback: function() {},
        getJsonpCallback: function (id) {
            var cb;
            var requests = this.requests;
            if (id in this.requests) {
                cb = function (result) { requests[id]._jsonp_callback(result); };
            } else {
                console.log("no callback with id " + id);
                cb = this.emptyCallback;
            }
            return cb;
        },
        addJsonpCallback: function (id, obj) {
            this.requests[id] = obj;
        },
        removeJsonpCallback: function (id) {
            delete this.requests[id];
        },
        newCallbackInfo: function () {
            var callbackInfo = {
                id: "cb-" + this.id,
                scriptId: "pd-jsonp-script-" + this.id
            };
            this.id++;
            return callbackInfo;
        }
    };

    var corsAvailable = "withCredentials" in new XMLHttpRequest();

    var Events = function () {
        this._events = {};
    };
    Events.prototype._getEventsForType = function (type) {
        if (!(type in this._events)) {
            this._events[type] = [];
        }
        return this._events[type];
    };
    Events.prototype._setEventsForType = function (type, events) {
        this._events[type] = events;
    };
    Events.prototype.on = function (type, handler) {
        var events = this._getEventsForType(type);
        events.push(handler);
    };
    Events.prototype.off = function (type) {
        if (arguments.length > 1) {
            var events = this._getEventsForType(type);
            var handlersToKeep = [];
            var handlers = Array.prototype.slice.call(arguments, 1);
            for (var i = 0; i < events.length; i++) {
                var event = events[i];
                var keep = true;
                for (var j = 0; j < handlers.length; j++) {
                    var handler = handlers[j];
                    if (event == handler) {
                        keep = false;
                    }
                }
                if (keep) {
                    handlersToKeep.push(event);
                }
            }
            this._setEventsForType(type, handlersToKeep);
        } else {
            delete this._events[type];
        }

    };
    Events.prototype.trigger = function (type, obj) {
        var args = Array.prototype.slice.call(arguments, 2);
        var events = this._getEventsForType(type);
        for (var i = 0; i < events.length; i++) {
            var handler = events[i];
            handler.apply(obj, args);
        }
    };

    var ErrorTypes = {
        "TransportError": 0,
        "TimeoutError": 1
    };

    var TransportTypes = {
        "Auto": 0,
        "Xhr": 1,
        "Jsonp": 2
    };

    var Request = function (config) {
        if (!(this instanceof Request)) {
            throw new Error("Constructor called as a function");
        }

        this._events = new Events();
        this._delayNext = false;

        this.rawResponse = false;
        this.maxTries = 1;
        this.maxDelay = 1000;

        if (config !== undefined) {
            if (config.transport !== undefined)
                this.transport = config.transport;
            if (config.rawResponse !== undefined)
                this.rawResponse = config.rawResponse;
            if (config.maxTries !== undefined)
                this.maxTries = config.maxTries;
            if (config.maxDelay !== undefined)
                this.maxDelay = config.maxDelay;
        }
    };
    Request.prototype.transport = TransportTypes.Auto;
    Request.prototype.start = function (method, url, headers, body) {
        var self = this;

        self._tries = 0;

        var delaytime;
        if (self._delayNext) {
            self._delayNext = false;
            delaytime = Math.floor(Math.random() * self.maxDelay);
            console.log("PD: polling again in " + delaytime + "ms");
        } else {
            delaytime = 0; // always queue the call, to prevent browser "busy"
        }

        self._method = method;
        self._url = url;
        self._headers = headers;
        self._body = body;

        self._timer = setTimeout(function() { self._connect(); }, delaytime);
    };
    Request.prototype.retry = function () {
        this._retry();
    };
    Request.prototype._connect = function () {
        var self = this;
        self._timer = window.setTimeout(function () { self._timeout(); }, TIMEOUT);

        ++self._tries;

        if (self.transport == TransportTypes.Auto) {
            if (corsAvailable) {
                self.transport = TransportTypes.Xhr;
            } else {
                self.transport = TransportTypes.Jsonp;
            }
        }

        if (self.transport == TransportTypes.Xhr) {

            self._xhr = new XMLHttpRequest();
            self._xhr.onreadystatechange = function () { self._xhr_readystatechange(); };
            self._xhr.open(self._method, self._url, true);

            for (var key in self._headers) {
                if (self._headers.hasOwnProperty(key)) {
                    self._xhr.setRequestHeader(key, self._headers[key]);
                }
            }

            self._xhr.send(self._body);

            console.log("PD: xhr " + self._url + " " + self._body);

        } else { // Jsonp

            this._callbackInfo = JsonCallbacks.newCallbackInfo();

            var paramList = [];

            paramList.push("_callback=" + encodeURIComponent("PollDance._getJsonpCallback(\"" + this._callbackInfo.id + "\")"));
            if (self._method != "GET") {
                paramList.push("_method=" + encodeURIComponent(self._method));
            }
            if (self._headers) {
                paramList.push("_headers=" + encodeURIComponent(JSON.stringify(self._headers)));
            }
            if (self._body) {
                paramList.push("_body=" + encodeURIComponent(self._body));
            }
            var params = paramList.join("&");

            var src;
            if (self._url.indexOf("?") != -1) {
                src = self._url + "&" + params;
            } else {
                src = self._url + "?" + params;
            }

            console.log("PD: json-p " + this._callbackInfo.id + " " + src);
            this._addJsonpCallback(this._callbackInfo, src);
        }
    };
    Request.prototype.abort = function () {
        clearTimeout(this._timer);
        this._timer = null;
        this._cancelreq();
    };
    Request.prototype.on = function (type, handler) {
        this._events.on(type, handler);
    };
    Request.prototype.off = function (type) {
        var args = Array.prototype.slice.call(arguments);
        this._events.off.apply(this._events, args);
    };
    Request.prototype._addJsonpCallback = function (callbackInfo, src) {
        JsonCallbacks.addJsonpCallback(callbackInfo.id, this);

        var head = document.getElementsByTagName("head")[0];
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.id = callbackInfo.scriptId;
        script.src = src;
        head.appendChild(script);
    };
    Request.prototype._removeJsonpCallback = function (callbackInfo) {
        JsonCallbacks.removeJsonpCallback(callbackInfo.id, this);

        var script = document.getElementById(callbackInfo.scriptId);
        script.parentNode.removeChild(script);
    };
    Request.prototype._cancelreq = function () {
        if (this.transport == TransportTypes.Xhr) {
            this._xhr.onreadystatechange = function () { }
            this._xhr.abort();
            this._xhr = null;
        } else { // Jsonp
            console.log("PD: json-p " + this._callbackInfo.id + " cancel");
            this._removeJsonpCallback(this._callbackInfo);
            this._callbackInfo = null;
        }
    };
    Request.prototype._xhr_readystatechange = function () {
        var xhr = this._xhr;
        if (xhr != null && xhr.readyState === 4) {
            this._xhr = null;

            window.clearTimeout(this._timer);
            this._timer = null;

            if (xhr.status) {
                if (xhr.status >= 500 && xhr.status <= 599 && (this.maxTries == -1 || this._tries < this.maxTries)) {
                    this._retry();
                } else {
                    // TODO: xhr.getAllResponseHeaders()
                    this._handle_response(xhr.status, xhr.statusText, {}, xhr.responseText);
                }
            } else {
                if (this.maxTries == -1 || this._tries < this.maxTries) {
                    this._retry();
                } else {
                    this._error(ErrorTypes.TransportError);
                }
            }
        }
    };
    Request.prototype._jsonp_callback = function (result) {
        console.log("PD: json-p " + this._callbackInfo.id + " finished");

        window.clearTimeout(this._timer);
        this._timer = null;

        this._removeJsonpCallback(this._callbackInfo);
        this._callbackInfo = null;

        var headers;
        if (result.headers !== undefined) {
            headers = result.headers;
        } else {
            headers = {};
        }

        this._handle_response(result.code, result.status, headers, result.body);
    };
    Request.prototype._handle_response = function (code, status, headers, body) {
         var result;
         if (this.rawResponse) {
             result = body;
         } else {
             try {
                 result = JSON.parse(body);
             } catch (e) {
                 result = body;
             }
         }
         this._finished(code, result, headers);
    };
    Request.prototype._timeout = function () {
        this._timer = null;
        this._cancelreq();

        if (this.maxTries == -1 || this._tries < this.maxTries) {
            this._retry();
        } else {
            this._error(ErrorTypes.TimeoutError);
        }
    };
    Request.prototype._retry = function() {
        if (this._tries === 1) {
            this._retryTime = 1;
        } else if (this._tries < 8) {
            this._retryTime = this._retryTime * 2;
        }

        var delaytime = this._retryTime * 1000;
        delaytime += Math.floor(Math.random() * this.maxDelay);
        console.log("PD: trying again in " + delaytime + "ms");

        var self = this;
        self._timer = setTimeout(function() { self._connect(); }, delaytime);
    };
    Request.prototype._finished = function (code, result, headers) {
        this._delayNext = true;
        this._events.trigger('finished', this, code, result, headers);
    };
    Request.prototype._error = function (reason) {
        this._delayNext = true;
        this._events.trigger('error', this, reason);
    };

    var pollDance = {
        Request: Request,
        _getJsonpCallback: function (id) {
            return JsonCallbacks.getJsonpCallback(id);
        }
    };

    window.PollDance = window.PollDance || pollDance;

})(window);
<commit_msg>only use json-p on non-cors browsers if not same origin<commit_after>(function (window, undefined) {

    var TIMEOUT = 60000;

    // don't break if there's no console
    if (typeof (window.console) === "undefined") {
        window.console = { log: function () { }, dir: function () { } };
    }

    // PollDance.Request has on('finished', int code, object result, object headers) and on('error', int reason) callback members

    var JsonCallbacks = {
        id: 0,
        requests: {},
        emptyCallback: function() {},
        getJsonpCallback: function (id) {
            var cb;
            var requests = this.requests;
            if (id in this.requests) {
                cb = function (result) { requests[id]._jsonp_callback(result); };
            } else {
                console.log("no callback with id " + id);
                cb = this.emptyCallback;
            }
            return cb;
        },
        addJsonpCallback: function (id, obj) {
            this.requests[id] = obj;
        },
        removeJsonpCallback: function (id) {
            delete this.requests[id];
        },
        newCallbackInfo: function () {
            var callbackInfo = {
                id: "cb-" + this.id,
                scriptId: "pd-jsonp-script-" + this.id
            };
            this.id++;
            return callbackInfo;
        }
    };

    var corsAvailable = "withCredentials" in new XMLHttpRequest();

    function sameOrigin(url) {
        var loc = window.location;
        var a = document.createElement('a');
        a.href = url;
        return !a.hostname || (a.hostname == loc.hostname && a.port == loc.port && a.protocol == loc.protocol);
    }

    var Events = function () {
        this._events = {};
    };
    Events.prototype._getEventsForType = function (type) {
        if (!(type in this._events)) {
            this._events[type] = [];
        }
        return this._events[type];
    };
    Events.prototype._setEventsForType = function (type, events) {
        this._events[type] = events;
    };
    Events.prototype.on = function (type, handler) {
        var events = this._getEventsForType(type);
        events.push(handler);
    };
    Events.prototype.off = function (type) {
        if (arguments.length > 1) {
            var events = this._getEventsForType(type);
            var handlersToKeep = [];
            var handlers = Array.prototype.slice.call(arguments, 1);
            for (var i = 0; i < events.length; i++) {
                var event = events[i];
                var keep = true;
                for (var j = 0; j < handlers.length; j++) {
                    var handler = handlers[j];
                    if (event == handler) {
                        keep = false;
                    }
                }
                if (keep) {
                    handlersToKeep.push(event);
                }
            }
            this._setEventsForType(type, handlersToKeep);
        } else {
            delete this._events[type];
        }

    };
    Events.prototype.trigger = function (type, obj) {
        var args = Array.prototype.slice.call(arguments, 2);
        var events = this._getEventsForType(type);
        for (var i = 0; i < events.length; i++) {
            var handler = events[i];
            handler.apply(obj, args);
        }
    };

    var ErrorTypes = {
        "TransportError": 0,
        "TimeoutError": 1
    };

    var TransportTypes = {
        "Auto": 0,
        "Xhr": 1,
        "Jsonp": 2
    };

    var Request = function (config) {
        if (!(this instanceof Request)) {
            throw new Error("Constructor called as a function");
        }

        this._events = new Events();
        this._delayNext = false;

        this.rawResponse = false;
        this.maxTries = 1;
        this.maxDelay = 1000;

        if (config !== undefined) {
            if (config.transport !== undefined)
                this.transport = config.transport;
            if (config.rawResponse !== undefined)
                this.rawResponse = config.rawResponse;
            if (config.maxTries !== undefined)
                this.maxTries = config.maxTries;
            if (config.maxDelay !== undefined)
                this.maxDelay = config.maxDelay;
        }
    };
    Request.prototype.transport = TransportTypes.Auto;
    Request.prototype.start = function (method, url, headers, body) {
        var self = this;

        self._tries = 0;

        var delaytime;
        if (self._delayNext) {
            self._delayNext = false;
            delaytime = Math.floor(Math.random() * self.maxDelay);
            console.log("PD: polling again in " + delaytime + "ms");
        } else {
            delaytime = 0; // always queue the call, to prevent browser "busy"
        }

        self._method = method;
        self._url = url;
        self._headers = headers;
        self._body = body;

        self._timer = setTimeout(function() { self._connect(); }, delaytime);
    };
    Request.prototype.retry = function () {
        this._retry();
    };
    Request.prototype._connect = function () {
        var self = this;
        self._timer = window.setTimeout(function () { self._timeout(); }, TIMEOUT);

        ++self._tries;

        if (self.transport == TransportTypes.Auto) {
            if (corsAvailable || sameOrigin(self._url)) {
                self.transport = TransportTypes.Xhr;
            } else {
                self.transport = TransportTypes.Jsonp;
            }
        }

        if (self.transport == TransportTypes.Xhr) {

            self._xhr = new XMLHttpRequest();
            self._xhr.onreadystatechange = function () { self._xhr_readystatechange(); };
            self._xhr.open(self._method, self._url, true);

            for (var key in self._headers) {
                if (self._headers.hasOwnProperty(key)) {
                    self._xhr.setRequestHeader(key, self._headers[key]);
                }
            }

            self._xhr.send(self._body);

            console.log("PD: xhr " + self._url + " " + self._body);

        } else { // Jsonp

            this._callbackInfo = JsonCallbacks.newCallbackInfo();

            var paramList = [];

            paramList.push("_callback=" + encodeURIComponent("PollDance._getJsonpCallback(\"" + this._callbackInfo.id + "\")"));
            if (self._method != "GET") {
                paramList.push("_method=" + encodeURIComponent(self._method));
            }
            if (self._headers) {
                paramList.push("_headers=" + encodeURIComponent(JSON.stringify(self._headers)));
            }
            if (self._body) {
                paramList.push("_body=" + encodeURIComponent(self._body));
            }
            var params = paramList.join("&");

            var src;
            if (self._url.indexOf("?") != -1) {
                src = self._url + "&" + params;
            } else {
                src = self._url + "?" + params;
            }

            console.log("PD: json-p " + this._callbackInfo.id + " " + src);
            this._addJsonpCallback(this._callbackInfo, src);
        }
    };
    Request.prototype.abort = function () {
        clearTimeout(this._timer);
        this._timer = null;
        this._cancelreq();
    };
    Request.prototype.on = function (type, handler) {
        this._events.on(type, handler);
    };
    Request.prototype.off = function (type) {
        var args = Array.prototype.slice.call(arguments);
        this._events.off.apply(this._events, args);
    };
    Request.prototype._addJsonpCallback = function (callbackInfo, src) {
        JsonCallbacks.addJsonpCallback(callbackInfo.id, this);

        var head = document.getElementsByTagName("head")[0];
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.id = callbackInfo.scriptId;
        script.src = src;
        head.appendChild(script);
    };
    Request.prototype._removeJsonpCallback = function (callbackInfo) {
        JsonCallbacks.removeJsonpCallback(callbackInfo.id, this);

        var script = document.getElementById(callbackInfo.scriptId);
        script.parentNode.removeChild(script);
    };
    Request.prototype._cancelreq = function () {
        if (this.transport == TransportTypes.Xhr) {
            this._xhr.onreadystatechange = function () { }
            this._xhr.abort();
            this._xhr = null;
        } else { // Jsonp
            console.log("PD: json-p " + this._callbackInfo.id + " cancel");
            this._removeJsonpCallback(this._callbackInfo);
            this._callbackInfo = null;
        }
    };
    Request.prototype._xhr_readystatechange = function () {
        var xhr = this._xhr;
        if (xhr != null && xhr.readyState === 4) {
            this._xhr = null;

            window.clearTimeout(this._timer);
            this._timer = null;

            if (xhr.status) {
                if (xhr.status >= 500 && xhr.status <= 599 && (this.maxTries == -1 || this._tries < this.maxTries)) {
                    this._retry();
                } else {
                    // TODO: xhr.getAllResponseHeaders()
                    this._handle_response(xhr.status, xhr.statusText, {}, xhr.responseText);
                }
            } else {
                if (this.maxTries == -1 || this._tries < this.maxTries) {
                    this._retry();
                } else {
                    this._error(ErrorTypes.TransportError);
                }
            }
        }
    };
    Request.prototype._jsonp_callback = function (result) {
        console.log("PD: json-p " + this._callbackInfo.id + " finished");

        window.clearTimeout(this._timer);
        this._timer = null;

        this._removeJsonpCallback(this._callbackInfo);
        this._callbackInfo = null;

        var headers;
        if (result.headers !== undefined) {
            headers = result.headers;
        } else {
            headers = {};
        }

        this._handle_response(result.code, result.status, headers, result.body);
    };
    Request.prototype._handle_response = function (code, status, headers, body) {
         var result;
         if (this.rawResponse) {
             result = body;
         } else {
             try {
                 result = JSON.parse(body);
             } catch (e) {
                 result = body;
             }
         }
         this._finished(code, result, headers);
    };
    Request.prototype._timeout = function () {
        this._timer = null;
        this._cancelreq();

        if (this.maxTries == -1 || this._tries < this.maxTries) {
            this._retry();
        } else {
            this._error(ErrorTypes.TimeoutError);
        }
    };
    Request.prototype._retry = function() {
        if (this._tries === 1) {
            this._retryTime = 1;
        } else if (this._tries < 8) {
            this._retryTime = this._retryTime * 2;
        }

        var delaytime = this._retryTime * 1000;
        delaytime += Math.floor(Math.random() * this.maxDelay);
        console.log("PD: trying again in " + delaytime + "ms");

        var self = this;
        self._timer = setTimeout(function() { self._connect(); }, delaytime);
    };
    Request.prototype._finished = function (code, result, headers) {
        this._delayNext = true;
        this._events.trigger('finished', this, code, result, headers);
    };
    Request.prototype._error = function (reason) {
        this._delayNext = true;
        this._events.trigger('error', this, reason);
    };

    var pollDance = {
        Request: Request,
        _getJsonpCallback: function (id) {
            return JsonCallbacks.getJsonpCallback(id);
        }
    };

    window.PollDance = window.PollDance || pollDance;

})(window);
<|endoftext|>


<commit_before>/* global Log, Module, moment, config */
/* Magic Mirror
 * Module: MMM-NetworkScanner
 *
 * By Ian Perrin http://ianperrin.com
 * MIT Licensed.
 */

//var Module, Log, moment, config, Log, moment, document;

Module.register("MMM-NetworkScanner", {

     // Default module config.
    defaults: {
        devices: [],                    // an array of device objects e.g. { macAddress: "aa:bb:cc:11:22:33", name: "DEVICE-NAME", icon: "FONT-AWESOME-ICON"}
        showUnknown: false,              // shows devices found on the network even if not specified in the 'devices' option
        showOffline: true,              // shows devices specified in the 'devices' option even when offline
        keepAlive: 300,                 // how long (in seconds) a device should be considered 'alive' since it was last found on the network
        updateInterval: 30,             // how often (in seconds) the module should scan the network

        residents: [],
        residents: ["Ben"],
        occupiedCMD: {notification: 'TEST', payload: {action: 'occupiedCMD'}},
        vacantCMD:   {notification: 'TEST', payload: {action: 'vacantCMD'}},
        debug: true,
    },

    // Subclass start method.
    start: function () {
        var self = this;
        Log.info("Starting module: " + this.name);

        if ( this.config.debug) {
            console.log("Config settings for " + this.name);
            console.log(this.config);
        }

        // variable for if anyone is home
        this.occupied = true;

        // variable for list of IP addresses
        self.IPAddresses = [];
        this.config.devices.forEach(function (device) {
//        for (var i=0; i<this.config.devices.length; i++) {
//           var device = this.config.devices[i];
            if (device.hasOwnProperty("ipAddress")) {
                self.IPAddresses.push(device);
            }
        });

        moment.locale(config.language);
        this.scanNetwork();
    },

    // Subclass getStyles method.
    getStyles: function () {
        return ['font-awesome.css'];
    },

    // Subclass getScripts method.
    getScripts: function () {
        return ["moment.js"];
    },

    // Subclass socketNotificationReceived method.
    socketNotificationReceived: function (notification, payload) {
//        Log.info(this.name + " received a notification: " + notification);
//        console.log("with payload: " + payload);

        var self = this;

        if (notification === 'IP_ADDRESS') {

            this.config.devices.forEach(function (device) {
//            for (var i=0; i < this.config.devices.length; i++) {
//               var device = this.config.devices[i];
                if (device.hasOwnProperty("ipAddress")) {
                    if (payload.name === device.name) {
                        device.online = payload.online;
                        if (payload.online) {
                           device.lastSeen = moment();
                        }
                        return;
                    }
                }
            });
        }

        if (notification === 'MAC_ADDRESSES') {
            // No action if data is the same
            if (JSON.stringify(this.networkDevices) === JSON.stringify(payload)) {
                return;
            }

            // Build device status list
//            var that = this;
            self.networkDevices = [];

            payload.forEach(function (item) {
//            for (var i = 0; i < payload.length - 1; i++) {
//                var item = payload[i]
                var device = self.getDeviceByMacAddress(item);
                console.log("devices: " + device);
                if (device) {
                    device.online = true;
                    device.lastSeen = moment();
                    self.networkDevices.push(device);
                }
            });
            console.log(self.networkDevices)

            // Add offline known devices
            if (self.config.showOffline) {
                console.log("Adding offline devices: ");

                self.config.devices.forEach(function (device) {
//                for (var d = 0; d < this.config.devices.length; d++) {
//                    var device = this.config.devices[d];

//                    console.log("Looking at device: ");
//                    console.log(device);
                    // Make sure we are using a device with a mac address
                    if (device.hasOwnProperty("macAddress")) {

                        self.networkDevices.forEach(function (networkDevice) {
//                        for (var n = 0; n < this.networkDevices.length; n++){
//                            var networkDevice = networkDevices[n];

                            // Find if the device is a known device
                            if (networkDevice.hasOwnProperty("macAddress")) {
                                if (networkDevice.macAddress.toUpperCase() === device.macAddress.toUpperCase()) {
                                    if (device.lastSeen) {
                                        device.online = (moment().diff(device.lastSeen, 'seconds') < self.config.keepAlive);
                                        Log.info(self.name + " is keeping alive " + device.name + ". Last seen " + device.lastSeen.fromNow());
                                    } else {
                                        device.online = false;
                                    }
                                }
                            }

                        });

                    } else if (device.hasOwnProperty("ipAddress")) {
                     // Keep the device alive incase of temporary loss

                        if (!device.online) {
                            console.log("device is not online");
                            if (device.lastSeen) {
                                device.online = (moment().diff(device.lastSeen, 'seconds') < self.config.keepAlive);
                                Log.info(self.name + " is keeping alive " + device.name + ". Last seen " + device.lastSeen.fromNow());
                            } else {
                                device.online = false;
                            }
                        }
                    }
                    self.networkDevices.push(device);
                });
            }

            // Sort list by known device names, then unknown device mac addresses
            this.networkDevices.sort(function (a, b) {
                var stringA, stringB;
                stringA = (a.name ? "_" + a.name : a.macAddress);
                stringB = (b.name ? "_" + b.name : b.macAddress);

                return stringA.localeCompare(stringB);
            });

            // Send notification if user status has changed
            if (self.config.residents.length > 0) {
                var anyoneHome, command;
//                self = this;
                anyoneHome = 0;

//              Array.prototype.contains = function (element) {
//                  return this.indexOf(element) > -1;
//              };

                this.networkDevices.forEach(function (device) {
//                for (var i=0; i<this.networkDevices.length; i++) {
//                    device = this.networkDevices[i];
                    if (self.config.residents.indexOf(device.name) >= 0) {
//                  if (self.config.residents.contains(device.name)) {
                        anyoneHome = anyoneHome + device.online;
                    }
                });

                console.log("# people home: ", anyoneHome);
                console.log("Was occupied? ", this.occupied);

                if (anyoneHome > 0) {
                    if (self.occupied === false) {
                        console.log("Someone has come home");
                        command = self.config.occupiedCMD;
                        self.sendNotification(command.notification, command.payload);
                        self.occupied = true;
                    }
                } else {
                    if (self.occupied === true) {
                        console.log("Everyone has left home");
                        command = self.config.vacantCMD;
                        self.sendNotification(command.notification, command.payload);
                        self.occupied = false;
                    }
                }
            }

            this.updateDom();
            return;

        }

    },

    // Override dom generator.
    getDom: function () {
        //Log.info(this.name + " is updating the DOM");
        var wrapper, deviceList, icon, deviceItem, deviceOnline, self;
        wrapper = document.createElement("div");

        self = this;

        wrapper.classList.add("small");

        // Display a loading message
        if (!this.networkDevices) {
            wrapper.innerHTML = this.translate("LOADING");
            return wrapper;
        }

        // Display device status
        deviceList = document.createElement("ul");
        deviceList.classList.add("fa-ul");
//        console.log("Network devices:");
//        console.log(self.networkDevices);
//        console.log(this.networkDevices);
        self.networkDevices.forEach(function (device) {
//        for (var i = 0; i < this.networkDevices.length; i++) {
//            var device = this.networkDevices[i];
            if (device) {

                // Add device items if they don't exist.
                if (!device.hasOwnProperty("icon")) {
                    device.icon = "question";
                }
                if (!device.hasOwnProperty("name")) {
                    if (device.hasOwnProperty("macAddress")) {
                        device.name = device.macAddress;
                    } else if (device.hasOwnProperty("ipAddress")) {
                        device.name = device.ipAddress;
                    } else {
                        device.name = "Unknown";
                    }
                }

                // device list item
                deviceItem = document.createElement("li");
                deviceOnline = (device.online ? "bright" : "dimmed");
                deviceItem.classList.add(deviceOnline);

                // Icon
                icon =  document.createElement("i");
                icon.classList.add("fa-li", "fa", "fa-" + device.icon);
                deviceItem.appendChild(icon);

                // Name
                deviceItem.innerHTML += device.name;

                deviceList.appendChild(deviceItem);

            } else {
                Log.info("Online, but ignoring: '" + device + "'");
            }
        });
        if (deviceList.hasChildNodes()) {
            wrapper.appendChild(deviceList);
        } else {
            // Display no devices online message
            wrapper.innerHTML = this.translate("NO DEVICES ONLINE");
        }

        return wrapper;
    },

    scanNetwork: function () {
        var devices, self;
        self = this;
        devices = this.config.devices;
        this.sendSocketNotification('SCAN_NETWORK', devices);
        setInterval(function () {
            self.sendSocketNotification('SCAN_NETWORK', devices);
        }, this.config.updateInterval * 1000);
        return;
    },

    getDeviceByMacAddress: function (macAddress) {

        var self = this;

        // Find first device with matching macAddress
        self.config.devices.forEach(function (device) {
//        for (var i = 0; i < this.config.devices.length; i++) {
//            var device = this.config.devices[i];
            if (device.hasOwnProperty("macAddress")) {
                if (macAddress.toUpperCase() === device.macAddress.toUpperCase()) {
                    return device;
                }
            }
        });

        // Return macAddress (if showing unknown) or null
        if (self.config.showUnknown) {
            return {macAddress: macAddress};
        }
    },

});

<commit_msg>Reverted defualts back to defaults.<commit_after>/* global Log, Module, moment, config */
/* Magic Mirror
 * Module: MMM-NetworkScanner
 *
 * By Ian Perrin http://ianperrin.com
 * MIT Licensed.
 */

//var Module, Log, moment, config, Log, moment, document;

Module.register("MMM-NetworkScanner", {

     // Default module config.
    defaults: {
        devices: [],                    // an array of device objects e.g. { macAddress: "aa:bb:cc:11:22:33", name: "DEVICE-NAME", icon: "FONT-AWESOME-ICON"}
        showUnknown: true,              // shows devices found on the network even if not specified in the 'devices' option
        showOffline: true,              // shows devices specified in the 'devices' option even when offline
        keepAlive: 180,                 // how long (in seconds) a device should be considered 'alive' since it was last found on the network
        updateInterval: 10,             // how often (in seconds) the module should scan the network

        residents: [],
        occupiedCMD: {notification: 'TEST', payload: {action: 'occupiedCMD'}},
        vacantCMD:   {notification: 'TEST', payload: {action: 'vacantCMD'}},
        debug: false,
    },

    // Subclass start method.
    start: function () {
        var self = this;
        Log.info("Starting module: " + this.name);

        if ( this.config.debug) {
            console.log("Config settings for " + this.name);
            console.log(this.config);
        }

        // variable for if anyone is home
        this.occupied = true;

        // variable for list of IP addresses
        self.IPAddresses = [];
        this.config.devices.forEach(function (device) {
//        for (var i=0; i<this.config.devices.length; i++) {
//           var device = this.config.devices[i];
            if (device.hasOwnProperty("ipAddress")) {
                self.IPAddresses.push(device);
            }
        });

        moment.locale(config.language);
        this.scanNetwork();
    },

    // Subclass getStyles method.
    getStyles: function () {
        return ['font-awesome.css'];
    },

    // Subclass getScripts method.
    getScripts: function () {
        return ["moment.js"];
    },

    // Subclass socketNotificationReceived method.
    socketNotificationReceived: function (notification, payload) {
//        Log.info(this.name + " received a notification: " + notification);
//        console.log("with payload: " + payload);

        var self = this;

        if (notification === 'IP_ADDRESS') {

            this.config.devices.forEach(function (device) {
//            for (var i=0; i < this.config.devices.length; i++) {
//               var device = this.config.devices[i];
                if (device.hasOwnProperty("ipAddress")) {
                    if (payload.name === device.name) {
                        device.online = payload.online;
                        if (payload.online) {
                           device.lastSeen = moment();
                        }
                        return;
                    }
                }
            });
        }

        if (notification === 'MAC_ADDRESSES') {
            // No action if data is the same
            if (JSON.stringify(this.networkDevices) === JSON.stringify(payload)) {
                return;
            }

            // Build device status list
//            var that = this;
            self.networkDevices = [];

            payload.forEach(function (item) {
//            for (var i = 0; i < payload.length - 1; i++) {
//                var item = payload[i]
                var device = self.getDeviceByMacAddress(item);
                console.log("devices: " + device);
                if (device) {
                    device.online = true;
                    device.lastSeen = moment();
                    self.networkDevices.push(device);
                }
            });
            console.log(self.networkDevices)

            // Add offline known devices
            if (self.config.showOffline) {
                console.log("Adding offline devices: ");

                self.config.devices.forEach(function (device) {
//                for (var d = 0; d < this.config.devices.length; d++) {
//                    var device = this.config.devices[d];

//                    console.log("Looking at device: ");
//                    console.log(device);
                    // Make sure we are using a device with a mac address
                    if (device.hasOwnProperty("macAddress")) {

                        self.networkDevices.forEach(function (networkDevice) {
//                        for (var n = 0; n < this.networkDevices.length; n++){
//                            var networkDevice = networkDevices[n];

                            // Find if the device is a known device
                            if (networkDevice.hasOwnProperty("macAddress")) {
                                if (networkDevice.macAddress.toUpperCase() === device.macAddress.toUpperCase()) {
                                    if (device.lastSeen) {
                                        device.online = (moment().diff(device.lastSeen, 'seconds') < self.config.keepAlive);
                                        Log.info(self.name + " is keeping alive " + device.name + ". Last seen " + device.lastSeen.fromNow());
                                    } else {
                                        device.online = false;
                                    }
                                }
                            }

                        });

                    } else if (device.hasOwnProperty("ipAddress")) {
                     // Keep the device alive incase of temporary loss

                        if (!device.online) {
                            console.log("device is not online");
                            if (device.lastSeen) {
                                device.online = (moment().diff(device.lastSeen, 'seconds') < self.config.keepAlive);
                                Log.info(self.name + " is keeping alive " + device.name + ". Last seen " + device.lastSeen.fromNow());
                            } else {
                                device.online = false;
                            }
                        }
                    }
                    self.networkDevices.push(device);
                });
            }

            // Sort list by known device names, then unknown device mac addresses
            this.networkDevices.sort(function (a, b) {
                var stringA, stringB;
                stringA = (a.name ? "_" + a.name : a.macAddress);
                stringB = (b.name ? "_" + b.name : b.macAddress);

                return stringA.localeCompare(stringB);
            });

            // Send notification if user status has changed
            if (self.config.residents.length > 0) {
                var anyoneHome, command;
//                self = this;
                anyoneHome = 0;

//              Array.prototype.contains = function (element) {
//                  return this.indexOf(element) > -1;
//              };

                this.networkDevices.forEach(function (device) {
//                for (var i=0; i<this.networkDevices.length; i++) {
//                    device = this.networkDevices[i];
                    if (self.config.residents.indexOf(device.name) >= 0) {
//                  if (self.config.residents.contains(device.name)) {
                        anyoneHome = anyoneHome + device.online;
                    }
                });

                console.log("# people home: ", anyoneHome);
                console.log("Was occupied? ", this.occupied);

                if (anyoneHome > 0) {
                    if (self.occupied === false) {
                        console.log("Someone has come home");
                        command = self.config.occupiedCMD;
                        self.sendNotification(command.notification, command.payload);
                        self.occupied = true;
                    }
                } else {
                    if (self.occupied === true) {
                        console.log("Everyone has left home");
                        command = self.config.vacantCMD;
                        self.sendNotification(command.notification, command.payload);
                        self.occupied = false;
                    }
                }
            }

            this.updateDom();
            return;

        }

    },

    // Override dom generator.
    getDom: function () {
        //Log.info(this.name + " is updating the DOM");
        var wrapper, deviceList, icon, deviceItem, deviceOnline, self;
        wrapper = document.createElement("div");

        self = this;

        wrapper.classList.add("small");

        // Display a loading message
        if (!this.networkDevices) {
            wrapper.innerHTML = this.translate("LOADING");
            return wrapper;
        }

        // Display device status
        deviceList = document.createElement("ul");
        deviceList.classList.add("fa-ul");
//        console.log("Network devices:");
//        console.log(self.networkDevices);
//        console.log(this.networkDevices);
        self.networkDevices.forEach(function (device) {
//        for (var i = 0; i < this.networkDevices.length; i++) {
//            var device = this.networkDevices[i];
            if (device) {

                // Add device items if they don't exist.
                if (!device.hasOwnProperty("icon")) {
                    device.icon = "question";
                }
                if (!device.hasOwnProperty("name")) {
                    if (device.hasOwnProperty("macAddress")) {
                        device.name = device.macAddress;
                    } else if (device.hasOwnProperty("ipAddress")) {
                        device.name = device.ipAddress;
                    } else {
                        device.name = "Unknown";
                    }
                }

                // device list item
                deviceItem = document.createElement("li");
                deviceOnline = (device.online ? "bright" : "dimmed");
                deviceItem.classList.add(deviceOnline);

                // Icon
                icon =  document.createElement("i");
                icon.classList.add("fa-li", "fa", "fa-" + device.icon);
                deviceItem.appendChild(icon);

                // Name
                deviceItem.innerHTML += device.name;

                deviceList.appendChild(deviceItem);

            } else {
                Log.info("Online, but ignoring: '" + device + "'");
            }
        });
        if (deviceList.hasChildNodes()) {
            wrapper.appendChild(deviceList);
        } else {
            // Display no devices online message
            wrapper.innerHTML = this.translate("NO DEVICES ONLINE");
        }

        return wrapper;
    },

    scanNetwork: function () {
        var devices, self;
        self = this;
        devices = this.config.devices;
        this.sendSocketNotification('SCAN_NETWORK', devices);
        setInterval(function () {
            self.sendSocketNotification('SCAN_NETWORK', devices);
        }, this.config.updateInterval * 1000);
        return;
    },

    getDeviceByMacAddress: function (macAddress) {

        var self = this;

        // Find first device with matching macAddress
        self.config.devices.forEach(function (device) {
//        for (var i = 0; i < this.config.devices.length; i++) {
//            var device = this.config.devices[i];
            if (device.hasOwnProperty("macAddress")) {
                if (macAddress.toUpperCase() === device.macAddress.toUpperCase()) {
                    return device;
                }
            }
        });

        // Return macAddress (if showing unknown) or null
        if (self.config.showUnknown) {
            return {macAddress: macAddress};
        }
    },

});

<|endoftext|>


<commit_before><commit_msg>build<commit_after><|endoftext|>


<commit_before>var $;
$ = jQuery;
$.fn.extend({
  geminiUpload: function(options) {
    var encodedCredentials;
    encodedCredentials = this.encode(options.geminiKey, '');
    return $.ajax({
      type: 'GET',
      dataType: 'json',
      url: "" + options.geminiApp + "/uploads/new.json",
      data: {
        acl: options.acl
      },
      headers: {
        'Authorization': "Basic " + encodedCredentials
      },
      success: (function(_this) {
        return function(resp) {
          return _this.attachFileUploadUI(resp, _.extend(options, {
            credentials: encodedCredentials
          }));
        };
      })(this)
    });
  },
  encode: function(key, secret) {
    return btoa(unescape(encodeURIComponent([key, secret].join(':'))));
  },
  uid: function() {
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return Array(16).join().split(',').map(function() { return chars.charAt(Math.floor(Math.random() * chars.length)); }).join('');
  },
  seedForm: function(data, options) {
    var $form, acl, base64Policy, bucket, key, s3Key, signature, successAction, uploadBucket;
    bucket = data.policy_document.conditions[0].bucket;
    key = "" + data.policy_document.conditions[1][2] + "/${filename}";
    acl = data.policy_document.conditions[2].acl;
    successAction = data.policy_document.conditions[3].success_action_status;
    base64Policy = data.policy_encoded;
    signature = data.signature;
    s3Key = options.s3Key;
    uploadBucket = bucket;
    $form = this.find('form');
    $form.find('input[name=key]').val(key);
    $form.find('input[name=AWSAccessKeyId]').val(s3Key);
    $form.find('input[name=acl]').val(acl);
    $form.find('input[name=success_action_status]').val(successAction);
    $form.find('input[name=policy]').val(base64Policy);
    $form.find('input[name=signature]').val(signature);
    if (typeof options.multiple != 'undefined' && options.multiple) {
      $form.find('input[name=file]').attr('multiple', true);
    }
    return $form.get(0).setAttribute('action', "https://" + uploadBucket + ".s3.amazonaws.com");
  },
  makeGeminiApiCall: function(data, originalKey, bucket, options, metadata) {
    var key = originalKey.replace('${filename}', data.uid);
    return $.ajax({
      type: 'POST',
      dataType: 'json',
      url: "" + options.geminiApp + "/entries.json",
      data: {
        entry: {
          source_key: key,
          source_bucket: bucket,
          template_key: options.templateKey,
          metadata: metadata,
          extract_geometry: options.extractGeometry
        }
      },
      headers: {
        'Authorization': "Basic " + options.credentials
      },
      success: function(resp) {
        if (typeof options.successCb != 'undefined' && options.successCb != null) {
          options.successCb(resp, metadata);
        }
      }
    });
  },
  attachFileUploadUI: function(data, options) {
    var $form, bucket, key, metadata, originalKey;

    $form = this.find('form');
    _.defaults(options, {pasteZone: undefined, dropZone: $form});
    bucket = data.policy_document.conditions[0].bucket;
    originalKey = "" + data.policy_document.conditions[1][2] + "/${filename}";
    this.seedForm(data, options);

    return $form.fileupload({
      type: 'POST',
      dataType: 'xml',
      pasteZone: options.pasteZone,
      dropZone: options.dropZone,
      done: (function(_this) {
        return function(e, data) {
          var fileName;
          if (typeof options.onDone != 'undefined' && options.onDone != null) {
            if (typeof options.useDataFromDone != 'undefined' && options.useDataFromDone) {
              options.onDone(e, data, originalKey, bucket, options, _this.makeGeminiApiCall)
            }
            else {
              options.onDone(e, data);
              _this.makeGeminiApiCall(data, originalKey, bucket, options, options.metadata);
            }
          }
        };
      })(this),
      add: (function(_this) {
        return function(e, data) {
          var fileName, fileType, uid, $key;
          uid = _this.uid();
          _.extend(data, { uid: uid });
          if (typeof options.onIndividualFile != 'undefined' && options.onIndividualFile != null) {
            options.onIndividualFile(e, data);
          }
          fileName = data.files[0].name;
          fileType = data.files[0].type;
          $(_this).find("form input[name='Content-Type']").val(fileType);
          $key = $form.find('input[name=key]');
          $key.val($key.val().replace(/[^\/]+$/, uid));
          return data.submit();
        };
      })(this),
      fail: options.onFail,
      progress: options.onProgress
    });
  }
});
<commit_msg>Use S3 key from Gemini credentials response, vs client options<commit_after>var $;
$ = jQuery;
$.fn.extend({
  geminiUpload: function(options) {
    var encodedCredentials;
    encodedCredentials = this.encode(options.geminiKey, '');
    return $.ajax({
      type: 'GET',
      dataType: 'json',
      url: "" + options.geminiApp + "/uploads/new.json",
      data: {
        acl: options.acl
      },
      headers: {
        'Authorization': "Basic " + encodedCredentials
      },
      success: (function(_this) {
        return function(resp) {
          return _this.attachFileUploadUI(resp, _.extend(options, {
            credentials: encodedCredentials
          }));
        };
      })(this)
    });
  },
  encode: function(key, secret) {
    return btoa(unescape(encodeURIComponent([key, secret].join(':'))));
  },
  uid: function() {
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return Array(16).join().split(',').map(function() { return chars.charAt(Math.floor(Math.random() * chars.length)); }).join('');
  },
  seedForm: function(data, options) {
    var $form, acl, base64Policy, bucket, key, s3Key, signature, successAction, uploadBucket;
    bucket = data.policy_document.conditions[0].bucket;
    key = "" + data.policy_document.conditions[1][2] + "/${filename}";
    acl = data.policy_document.conditions[2].acl;
    successAction = data.policy_document.conditions[3].success_action_status;
    base64Policy = data.policy_encoded;
    signature = data.signature;
    s3Key = data.credentials;
    uploadBucket = bucket;
    $form = this.find('form');
    $form.find('input[name=key]').val(key);
    $form.find('input[name=AWSAccessKeyId]').val(s3Key);
    $form.find('input[name=acl]').val(acl);
    $form.find('input[name=success_action_status]').val(successAction);
    $form.find('input[name=policy]').val(base64Policy);
    $form.find('input[name=signature]').val(signature);
    if (typeof options.multiple != 'undefined' && options.multiple) {
      $form.find('input[name=file]').attr('multiple', true);
    }
    return $form.get(0).setAttribute('action', "https://" + uploadBucket + ".s3.amazonaws.com");
  },
  makeGeminiApiCall: function(data, originalKey, bucket, options, metadata) {
    var key = originalKey.replace('${filename}', data.uid);
    return $.ajax({
      type: 'POST',
      dataType: 'json',
      url: "" + options.geminiApp + "/entries.json",
      data: {
        entry: {
          source_key: key,
          source_bucket: bucket,
          template_key: options.templateKey,
          metadata: metadata,
          extract_geometry: options.extractGeometry
        }
      },
      headers: {
        'Authorization': "Basic " + options.credentials
      },
      success: function(resp) {
        if (typeof options.successCb != 'undefined' && options.successCb != null) {
          options.successCb(resp, metadata);
        }
      }
    });
  },
  attachFileUploadUI: function(data, options) {
    var $form, bucket, key, metadata, originalKey;

    $form = this.find('form');
    _.defaults(options, {pasteZone: undefined, dropZone: $form});
    bucket = data.policy_document.conditions[0].bucket;
    originalKey = "" + data.policy_document.conditions[1][2] + "/${filename}";
    this.seedForm(data, options);

    return $form.fileupload({
      type: 'POST',
      dataType: 'xml',
      pasteZone: options.pasteZone,
      dropZone: options.dropZone,
      done: (function(_this) {
        return function(e, data) {
          var fileName;
          if (typeof options.onDone != 'undefined' && options.onDone != null) {
            if (typeof options.useDataFromDone != 'undefined' && options.useDataFromDone) {
              options.onDone(e, data, originalKey, bucket, options, _this.makeGeminiApiCall)
            }
            else {
              options.onDone(e, data);
              _this.makeGeminiApiCall(data, originalKey, bucket, options, options.metadata);
            }
          }
        };
      })(this),
      add: (function(_this) {
        return function(e, data) {
          var fileName, fileType, uid, $key;
          uid = _this.uid();
          _.extend(data, { uid: uid });
          if (typeof options.onIndividualFile != 'undefined' && options.onIndividualFile != null) {
            options.onIndividualFile(e, data);
          }
          fileName = data.files[0].name;
          fileType = data.files[0].type;
          $(_this).find("form input[name='Content-Type']").val(fileType);
          $key = $form.find('input[name=key]');
          $key.val($key.val().replace(/[^\/]+$/, uid));
          return data.submit();
        };
      })(this),
      fail: options.onFail,
      progress: options.onProgress
    });
  }
});
<|endoftext|>