<commit_before>var Cimpler  = require('../lib/cimpler'),
    Github   = require('../plugins/github'),
    http     = require('http'),
    assert   = require('assert'),
    expect   = require("./expect"),
    _        = require('underscore'),
    testConfig = require('./test-config.js'),
    httpPort = testConfig.httpPort;

var config = {a: 1},
pushCommit = "push1232322",
pullRequestCommit = "pullrequest1232322",
options = {
   port: httpPort,
   path: '/github',
   method: 'POST',
   agent: false,
   headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "X-GitHub-Event": "push"
   }
},
pushTestBranchName = "push-branch-name-with/slashes.and.dots",
pullRequestTestBranchName = "pull-request-branch-name-with/slashes.and.dots",
postBuild = {
   ref:"refs/heads/" + pushTestBranchName,
   repository:{full_name:"user/repo"},
   after: pushCommit,
   action: "synchronize",
   pull_request:{
      head: {
         ref: pullRequestTestBranchName,
         sha: pullRequestCommit
      }
   }
};

describe("Github plugin", function() {
   it("should listen for and add builds for push events",
   function(done) {
      // Set event type to 'push'
      options.headers["X-GitHub-Event"] = "push";

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      /**
       * Ensure "tag" notifications get filtered
       * (this shouldn't get to consumeBuild)
       */
      postBuild.ref = "refs/tags/some_tag";
      req = http.request(options);
      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function(build, started, finished) {
         assert.equal(cb, 0, "Only one build should get through");
         cb++;

         var sanitizedBuild = _.pick(build, 'repo', 'commit', 'branch', 'status')
         assert.deepEqual(sanitizedBuild, {
            repo:    'github.com/user/repo',
            commit:   pushCommit,
            branch:  pushTestBranchName,
            status:  'pending'
         });
         finished();
      });

      // Ensure this callback doesn't get called again by
      // delaying the done()
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 1, "Assert the callback was called once.");
         done();
      }, 100);
   });
   it("should listen for and add builds for pull_request sychronize events",
   function(done) {
      // Set event type to 'pull_request' and action to 'synchronize'
      options.headers["X-GitHub-Event"] = "pull_request";
      postBuild.action = 'synchronize';

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function(build, started, finished) {
         assert.equal(cb, 0, "Only one build should get through");
         cb++;

         var sanitizedBuild = _.pick(build, 'repo', 'commit', 'branch', 'status')
         assert.deepEqual(sanitizedBuild, {
            repo:    'github.com/user/repo',
            commit:   pullRequestCommit,
            branch:  pullRequestTestBranchName,
            status:  'pending'
         });
      finished();
      });

      // Ensure this callback doesn't get called again by
      // delaying the done()
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 1, "Assert the callback was called once.");
         done();
      }, 100);
   });
   it("should listen for and add builds for pull_request opened events",
   function(done) {
      // Set event type to 'pull_request' and action to 'opened'
      options.headers["X-GitHub-Event"] = "pull_request";
      postBuild.action = 'opened';

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function(build, started, finished) {
         assert.equal(cb, 0, "Only one build should get through");
         cb++;

         var sanitizedBuild = _.pick(build, 'repo', 'commit', 'branch', 'status')
         assert.deepEqual(sanitizedBuild, {
            repo:    'github.com/user/repo',
            commit:   pullRequestCommit,
            branch:  pullRequestTestBranchName,
            status:  'pending'
         });
         finished();

      });

      // Ensure this callback doesn't get called again by
      // delaying the done()
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 1, "Assert the callback was called once.");
         done();
      }, 100);
   });
   it("should listen but abort builds for pull_requests with actions other than synchronize and opened",
   function(done) {
      // Set event type to 'pull_request' and action to 'closed'
      options.headers["X-GitHub-Event"] = "pull_request";
      postBuild.action = 'closed';

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function() {
         cb++;
         assert.ok(false, "We should never consume a build.");
      });

      // Ensure we don't miss any requests
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 0, "consumeBuild should not have been called.");
         done();
      }, 100);
   });
});
<commit_msg>Github test: Fix assertions<commit_after>var Cimpler  = require('../lib/cimpler'),
    Github   = require('../plugins/github'),
    http     = require('http'),
    assert   = require('assert'),
    expect   = require("./expect"),
    _        = require('underscore'),
    testConfig = require('./test-config.js'),
    httpPort = testConfig.httpPort;

var config = {a: 1},
pushCommit = "push1232322",
pullRequestCommit = "pullrequest1232322",
options = {
   port: httpPort,
   path: '/github',
   method: 'POST',
   agent: false,
   headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "X-GitHub-Event": "push"
   }
},
pushTestBranchName = "push-branch-name-with/slashes.and.dots",
pullRequestTestBranchName = "pull-request-branch-name-with/slashes.and.dots",
postBuild = {
   ref:"refs/heads/" + pushTestBranchName,
   repository:{full_name:"user/repo"},
   after: pushCommit,
   action: "synchronize",
   pull_request:{
      head: {
         ref: pullRequestTestBranchName,
         sha: pullRequestCommit
      }
   }
};

describe("Github plugin", function() {
   it("should listen for and add builds for push events",
   function(done) {
      // Set event type to 'push'
      options.headers["X-GitHub-Event"] = "push";

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      /**
       * Ensure "tag" notifications get filtered
       * (this shouldn't get to consumeBuild)
       */
      postBuild.ref = "refs/tags/some_tag";
      req = http.request(options);
      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function(build, started, finished) {
         cb++;

         var sanitizedBuild = _.pick(build, 'repo', 'commit', 'branch', 'status')
         assert.deepEqual(sanitizedBuild, {
            repo:    'github.com/user/repo',
            commit:   pushCommit,
            branch:  pushTestBranchName,
            status:  'pending'
         });
         finished();
      });

      // Ensure this callback doesn't get called again by
      // delaying the done()
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 1, "Assert the callback was called once.");
         done();
      }, 100);
   });
   it("should listen for and add builds for pull_request sychronize events",
   function(done) {
      // Set event type to 'pull_request' and action to 'synchronize'
      options.headers["X-GitHub-Event"] = "pull_request";
      postBuild.action = 'synchronize';

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function(build, started, finished) {
         cb++;

         var sanitizedBuild = _.pick(build, 'repo', 'commit', 'branch', 'status')
         assert.deepEqual(sanitizedBuild, {
            repo:    'github.com/user/repo',
            commit:   pullRequestCommit,
            branch:  pullRequestTestBranchName,
            status:  'pending'
         });
      finished();
      });

      // Ensure this callback doesn't get called again by
      // delaying the done()
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 1, "Assert the callback was called once.");
         done();
      }, 100);
   });
   it("should listen for and add builds for pull_request opened events",
   function(done) {
      // Set event type to 'pull_request' and action to 'opened'
      options.headers["X-GitHub-Event"] = "pull_request";
      postBuild.action = 'opened';

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function(build, started, finished) {
         cb++;

         var sanitizedBuild = _.pick(build, 'repo', 'commit', 'branch', 'status')
         assert.deepEqual(sanitizedBuild, {
            repo:    'github.com/user/repo',
            commit:   pullRequestCommit,
            branch:  pullRequestTestBranchName,
            status:  'pending'
         });
         finished();

      });

      // Ensure this callback doesn't get called again by
      // delaying the done()
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 1, "Assert the callback was called once.");
         done();
      }, 100);
   });
   it("should listen but abort builds for pull_requests with actions other than synchronize and opened",
   function(done) {
      // Set event type to 'pull_request' and action to 'closed'
      options.headers["X-GitHub-Event"] = "pull_request";
      postBuild.action = 'closed';

      var cimpler = new Cimpler({
         httpPort: httpPort
      });

      cimpler.registerPlugin(Github, { });

      var check = expect(1, function(count) {
         assert.fail();
      });

      var req = http.request(options);

      // Pretend to be github and POST to our listener
      req.write("payload=" + encodeURIComponent(JSON.stringify(postBuild)));
      req.end();

      var cb = 0;
      cimpler.consumeBuild(function() {
         cb++;
      });

      // Ensure we don't miss any requests
      setTimeout(function() {
         cimpler.shutdown();
         assert.equal(cb, 0, "consumeBuild should not have been called.");
         done();
      }, 100);
   });
});
<|endoftext|>


<commit_before>'use strict';

const Serverless = require('serverless');
const execSync = require('child_process').execSync;
const path = require('path');
const fse = require('fs-extra');
const expect = require('chai').expect;
const testUtils = require('./testUtils');

const serverless = new Serverless();
serverless.init();
const serverlessExec = path.join(serverless.config.serverlessPath, '..', 'bin', 'serverless');

describe('integration', () => {
  before(() => {
    // create temporary directory and copy test service there
    process.env.MOCHA_PLUGIN_TEST_DIR = path.join(__dirname);
    const tmpDir = testUtils.getTmpDirPath();
    fse.mkdirsSync(tmpDir);
    fse.copySync(path.join(process.env.MOCHA_PLUGIN_TEST_DIR, 'test-service'), tmpDir);
    process.chdir(tmpDir);
  });

  it('should contain test params in cli info', () => {
    const test = execSync(`${serverlessExec}`);
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'create test ................... Create mocha tests for service / function'
    );
    expect(result).to.have.string(
      'create function ............... Create a function into the service'
    );
    expect(result).to.have.string(
      'invoke test ................... Invoke test(s)'
    );
  });

  it('should create test for hello function', () => {
    const test = execSync(`${serverlessExec} create test --function hello --stage dev`);
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'serverless-mocha-plugin: created test/hello.js'
    );
  });

  it('should create function goodbye', () => {
    const test = execSync(
      `${serverlessExec} create function --function goodbye --handler goodbye/index.handler --stage dev`
    );
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'serverless-mocha-plugin: created test/goodbye.js'
    );
  });

  it('should run tests successfully', () => {
    // change test files to use local proxy version of mocha plugin
    testUtils.replaceTextInFile(
      path.join('test', 'hello.js'),
      'require(\'serverless-mocha-plugin\')',
      'require(\'../.serverless_plugins/serverless-mocha-plugin/index.js\')'
    );
    testUtils.replaceTextInFile(
      path.join('test', 'goodbye.js'),
      'require(\'serverless-mocha-plugin\')',
      'require(\'../.serverless_plugins/serverless-mocha-plugin/index.js\')'
    );
    const test = execSync(`${serverlessExec} invoke test --stage dev --region us-east-1`);
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'goodbye\n    ✓ implement tests here'
    );

    expect(result).to.have.string(
      'hello\n    ✓ implement tests here'
    );

    expect(result).to.have.string(
      '2 passing'
    );
  });
});
<commit_msg>fix lint<commit_after>'use strict';

const Serverless = require('serverless');
const execSync = require('child_process').execSync;
const path = require('path');
const fse = require('fs-extra');
const expect = require('chai').expect;
const testUtils = require('./testUtils');

const serverless = new Serverless();
serverless.init();
const serverlessExec = path.join(serverless.config.serverlessPath, '..', 'bin', 'serverless');

describe('integration', () => {
  before(() => {
    // create temporary directory and copy test service there
    process.env.MOCHA_PLUGIN_TEST_DIR = path.join(__dirname);
    const tmpDir = testUtils.getTmpDirPath();
    fse.mkdirsSync(tmpDir);
    fse.copySync(path.join(process.env.MOCHA_PLUGIN_TEST_DIR, 'test-service'), tmpDir);
    process.chdir(tmpDir);
  });

  it('should contain test params in cli info', () => {
    const test = execSync(`${serverlessExec}`);
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'create test ................... Create mocha tests for service / function'
    );
    expect(result).to.have.string(
      'create function ............... Create a function into the service'
    );
    expect(result).to.have.string(
      'invoke test ................... Invoke test(s)'
    );
  });

  it('should create test for hello function', () => {
    const test = execSync(`${serverlessExec} create test --function hello --stage dev`);
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'serverless-mocha-plugin: created test/hello.js'
    );
  });

  it('should create function goodbye', () => {
    const test = execSync(
      `${serverlessExec}` +
      ' create function --function goodbye --handler goodbye/index.handler --stage dev'
    );
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'serverless-mocha-plugin: created test/goodbye.js'
    );
  });

  it('should run tests successfully', () => {
    // change test files to use local proxy version of mocha plugin
    testUtils.replaceTextInFile(
      path.join('test', 'hello.js'),
      'require(\'serverless-mocha-plugin\')',
      'require(\'../.serverless_plugins/serverless-mocha-plugin/index.js\')'
    );
    testUtils.replaceTextInFile(
      path.join('test', 'goodbye.js'),
      'require(\'serverless-mocha-plugin\')',
      'require(\'../.serverless_plugins/serverless-mocha-plugin/index.js\')'
    );
    const test = execSync(`${serverlessExec} invoke test --stage dev --region us-east-1`);
    const result = new Buffer(test, 'base64').toString();
    expect(result).to.have.string(
      'goodbye\n    ✓ implement tests here'
    );

    expect(result).to.have.string(
      'hello\n    ✓ implement tests here'
    );

    expect(result).to.have.string(
      '2 passing'
    );
  });
});
<|endoftext|>


<commit_before>suite('intree config', () => {
  let fs = require('fs');
  let assert = require('assert');
  let _ = require('lodash');
  let helper = require('./helper');

  /**
   * Test github data, like one would see in a pulse message
   * after a pull request
   **/
  function buildMessage(params) {
    let defaultMessage = {
      organization: 'testorg',
      repository:   'testrepo',
      details: {
        'event.pullNumber': 'eventData.number',
        'event.type': 'pull_request.opened',
        'event.base.user.login': 'eventData.pull_request.base.user.login',
        'event.base.repo.url': 'eventData.pull_request.base.repo.clone_url',
        'event.base.repo.branch': 'default_branch',
        'event.base.sha': 'eventData.pull_request.base.sha',
        'event.base.ref': 'eventData.pull_request.base.ref',
        'event.head.user.login': 'eventData.pull_request.head.user.login',
        'event.head.repo.url': 'eventData.pull_request.head.repo.clone_url',
        'event.head.repo.branch': 'eventData.pull_request.head.default_branch',
        'event.head.sha': 'eventData.pull_request.head.sha',
        'event.head.ref': 'eventData.pull_request.head.ref',
        'event.head.user.email': 'test@test.com',
      },
    };
    return _.merge(defaultMessage, params);
  };

  /**
   * Make sure that data merges properly when building configs
   * testName:    '', A label for the current test case
   * configPath:  '', Path to a taskclusterConfig file
   * params:      {
   *                payload:    {}, WebHook message payload
   *                validator:  {}, A taskcluster.base validator
   *              }
   * expected:    {}, keys=>values expected to exist in the compiled config
   **/
  let buildConfigTest = function(testName, configPath, params, expected) {
    test(testName, async () => {
      params.config = fs.readFileSync(configPath);
      params.schema = 'http://schemas.taskcluster.net/github/v1/taskcluster-github-config.json#';
      params.validator = helper.validator;
      let config = helper.intree(params);
      for (let key of Object.keys(expected)) {
        assert.deepEqual(_.get(config, key), expected[key]);
      }
    });
  };

  let configPath = 'test/data/configs/';

  buildConfigTest(
    'Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage(),
    },
    {
      tasks: [], // The github event doesn't match, so no tasks are created
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Pull Event, Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Push Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['push'],
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Pull Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage(),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['pull_request.opened', 'pull_request.synchronize', 'pull_request.reopened'],
      scopes: ['assume:repo:github.com/testorg/testrepo:pull-request'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:master'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });

  buildConfigTest(
    'Star Pull Config',
    configPath + 'taskcluster.star.yml',
    {
      payload:    buildMessage(),
    },
    {
      'tasks[0].task.extra.github.events': ['pull_request.*'],
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Release Event, Single Task Config',
    configPath + 'taskcluster.release_single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.release_branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.release_branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });
});
<commit_msg>Update intree_test.js<commit_after>suite('intree config', () => {
  let fs = require('fs');
  let assert = require('assert');
  let _ = require('lodash');
  let helper = require('./helper');

  /**
   * Test github data, like one would see in a pulse message
   * after a pull request
   **/
  function buildMessage(params) {
    let defaultMessage = {
      organization: 'testorg',
      repository:   'testrepo',
      details: {
        'event.pullNumber': 'eventData.number',
        'event.type': 'pull_request.opened',
        'event.base.user.login': 'eventData.pull_request.base.user.login',
        'event.base.repo.url': 'eventData.pull_request.base.repo.clone_url',
        'event.base.repo.branch': 'default_branch',
        'event.base.sha': 'eventData.pull_request.base.sha',
        'event.base.ref': 'eventData.pull_request.base.ref',
        'event.head.user.login': 'eventData.pull_request.head.user.login',
        'event.head.repo.url': 'eventData.pull_request.head.repo.clone_url',
        'event.head.repo.branch': 'eventData.pull_request.head.default_branch',
        'event.head.sha': 'eventData.pull_request.head.sha',
        'event.head.ref': 'eventData.pull_request.head.ref',
        'event.head.user.email': 'test@test.com',
      },
    };
    return _.merge(defaultMessage, params);
  };

  /**
   * Make sure that data merges properly when building configs
   * testName:    '', A label for the current test case
   * configPath:  '', Path to a taskclusterConfig file
   * params:      {
   *                payload:    {}, WebHook message payload
   *                validator:  {}, A taskcluster.base validator
   *              }
   * expected:    {}, keys=>values expected to exist in the compiled config
   **/
  let buildConfigTest = function(testName, configPath, params, expected) {
    test(testName, async () => {
      params.config = fs.readFileSync(configPath);
      params.schema = 'http://schemas.taskcluster.net/github/v1/taskcluster-github-config.json#';
      params.validator = helper.validator;
      let config = helper.intree(params);
      for (let key of Object.keys(expected)) {
        assert.deepEqual(_.get(config, key), expected[key]);
      }
    });
  };

  let configPath = 'test/data/configs/';

  buildConfigTest(
    'Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage(),
    },
    {
      tasks: [], // The github event doesn't match, so no tasks are created
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Pull Event, Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Push Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['push'],
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Pull Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage(),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['pull_request.opened', 'pull_request.synchronize', 'pull_request.reopened'],
      scopes: ['assume:repo:github.com/testorg/testrepo:pull-request'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:master'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });

  buildConfigTest(
    'Star Pull Config',
    configPath + 'taskcluster.star.yml',
    {
      payload:    buildMessage(),
    },
    {
      'tasks[0].task.extra.github.events': ['pull_request.*'],
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Release Event, Single Task Config',
    configPath + 'taskcluster.release_single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });
});
<|endoftext|>


<commit_before>suite('intree config', () => {
  let fs = require('fs');
  let assert = require('assert');
  let _ = require('lodash');
  let helper = require('./helper');

  /**
   * Test github data, like one would see in a pulse message
   * after a pull request
   **/
  function buildMessage(params) {
    let defaultMessage = {
      organization: 'testorg',
      repository:   'testrepo',
      details: {
        'event.pullNumber': 'eventData.number',
        'event.type': 'pull_request.opened',
        'event.base.user.login': 'eventData.pull_request.base.user.login',
        'event.base.repo.url': 'eventData.pull_request.base.repo.clone_url',
        'event.base.repo.branch': 'default_branch',
        'event.base.sha': 'eventData.pull_request.base.sha',
        'event.base.ref': 'eventData.pull_request.base.ref',
        'event.head.user.login': 'eventData.pull_request.head.user.login',
        'event.head.repo.url': 'eventData.pull_request.head.repo.clone_url',
        'event.head.repo.branch': 'eventData.pull_request.head.default_branch',
        'event.head.sha': 'eventData.pull_request.head.sha',
        'event.head.ref': 'eventData.pull_request.head.ref',
        'event.head.user.email': 'test@test.com',
      },
    };
    return _.merge(defaultMessage, params);
  };

  /**
   * Make sure that data merges properly when building configs
   * testName:    '', A label for the current test case
   * configPath:  '', Path to a taskclusterConfig file
   * params:      {
   *                payload:    {}, WebHook message payload
   *                validator:  {}, A taskcluster.base validator
   *              }
   * expected:    {}, keys=>values expected to exist in the compiled config
   **/
  let buildConfigTest = function(testName, configPath, params, expected) {
    test(testName, async () => {
      params.config = fs.readFileSync(configPath);
      params.schema = 'http://schemas.taskcluster.net/github/v1/taskcluster-github-config.json#';
      params.validator = helper.validator;
      let config = helper.intree(params);
      for (let key of Object.keys(expected)) {
        assert.deepEqual(_.get(config, key), expected[key]);
      }
    });
  };

  let configPath = 'test/data/configs/';

  buildConfigTest(
    'Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage(),
    },
    {
      tasks: [], // The github event doesn't match, so no tasks are created
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Pull Event, Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Push Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['push'],
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Pull Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage(),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['pull_request.opened', 'pull_request.synchronize', 'pull_request.reopened'],
      scopes: ['assume:repo:github.com/testorg/testrepo:pull-request'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:master'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });

  buildConfigTest(
    'Star Pull Config',
    configPath + 'taskcluster.star.yml',
    {
      payload:    buildMessage(),
    },
    {
      'tasks[0].task.extra.github.events': ['pull_request.*'],
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Release Event, Single Task Config',
    configPath + 'taskcluster.release_single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch:release'],
    });

  buildConfigTest(
    'Release Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch:release'],
    });

  buildConfigTest(
    'Release Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.release_branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:master:release'],
    });

  buildConfigTest(
    'Release Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.release_branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });
});
<commit_msg>Update intree_test.js<commit_after>suite('intree config', () => {
  let fs = require('fs');
  let assert = require('assert');
  let _ = require('lodash');
  let helper = require('./helper');

  /**
   * Test github data, like one would see in a pulse message
   * after a pull request
   **/
  function buildMessage(params) {
    let defaultMessage = {
      organization: 'testorg',
      repository:   'testrepo',
      details: {
        'event.pullNumber': 'eventData.number',
        'event.type': 'pull_request.opened',
        'event.base.user.login': 'eventData.pull_request.base.user.login',
        'event.base.repo.url': 'eventData.pull_request.base.repo.clone_url',
        'event.base.repo.branch': 'default_branch',
        'event.base.sha': 'eventData.pull_request.base.sha',
        'event.base.ref': 'eventData.pull_request.base.ref',
        'event.head.user.login': 'eventData.pull_request.head.user.login',
        'event.head.repo.url': 'eventData.pull_request.head.repo.clone_url',
        'event.head.repo.branch': 'eventData.pull_request.head.default_branch',
        'event.head.sha': 'eventData.pull_request.head.sha',
        'event.head.ref': 'eventData.pull_request.head.ref',
        'event.head.user.email': 'test@test.com',
      },
    };
    return _.merge(defaultMessage, params);
  };

  /**
   * Make sure that data merges properly when building configs
   * testName:    '', A label for the current test case
   * configPath:  '', Path to a taskclusterConfig file
   * params:      {
   *                payload:    {}, WebHook message payload
   *                validator:  {}, A taskcluster.base validator
   *              }
   * expected:    {}, keys=>values expected to exist in the compiled config
   **/
  let buildConfigTest = function(testName, configPath, params, expected) {
    test(testName, async () => {
      params.config = fs.readFileSync(configPath);
      params.schema = 'http://schemas.taskcluster.net/github/v1/taskcluster-github-config.json#';
      params.validator = helper.validator;
      let config = helper.intree(params);
      for (let key of Object.keys(expected)) {
        assert.deepEqual(_.get(config, key), expected[key]);
      }
    });
  };

  let configPath = 'test/data/configs/';

  buildConfigTest(
    'Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage(),
    },
    {
      tasks: [], // The github event doesn't match, so no tasks are created
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Pull Event, Single Task Config',
    configPath + 'taskcluster.single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Push Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push'}}),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['push'],
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:default_branch'],
    });

  buildConfigTest(
    'Pull Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage(),
    },
    {
      'metadata.owner': 'test@test.com',
      'tasks[0].task.payload.command': ['test'],
      'tasks[0].task.extra.github.events': ['pull_request.opened', 'pull_request.synchronize', 'pull_request.reopened'],
      scopes: ['assume:repo:github.com/testorg/testrepo:pull-request'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['push'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:branch:master'],
    });

  buildConfigTest(
    'Push Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'push', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });

  buildConfigTest(
    'Star Pull Config',
    configPath + 'taskcluster.star.yml',
    {
      payload:    buildMessage(),
    },
    {
      'tasks[0].task.extra.github.events': ['pull_request.*'],
      'metadata.owner': 'test@test.com',
    });

  buildConfigTest(
    'Release Event, Single Task Config',
    configPath + 'taskcluster.release_single.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event (Push Task + Pull Task + Release Task)',
    configPath + 'taskcluster.push_pull_release.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event, Single Task Config, Branch Limited (on branch)',
    configPath + 'taskcluster.release_branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release', 'event.base.repo.branch': 'master'}}),
    },
    {
      'tasks[0].task.extra.github.events': ['release'],
      'tasks[0].task.extra.github.branches': ['master'],
      'metadata.owner': 'test@test.com',
      scopes: ['assume:repo:github.com/testorg/testrepo:release'],
    });

  buildConfigTest(
    'Release Event, Single Task Config, Branch Limited (off branch)',
    configPath + 'taskcluster.release_branchlimited.yml',
    {
      payload:    buildMessage({details: {'event.type': 'release', 'event.base.repo.branch': 'foobar'}}),
    },
    {
      tasks: [],
    });
});
<|endoftext|>


<commit_before>var mongoose = require("mongoose");

var userSchema = new mongoose.Schema({
	auth: String,
	id: String,
	username: String,
	displayName: String,
	firstName: String,
	lastName: String,
	email: String,
	link: String,
	picture: String,
	gender: String,
	website: String,
	usertype: String,
	photos: Array,
	workedWith: Array
});

var jobSchema = new mongoose.Schema({
	user: String,
	dateAdded: Date,
	postingAs: String,
	eventName: String,
	dateTime: Date,
	jobDuration: String,
	location: String,
	description: String,
	useOfPhotos: Array,
	dateRequired: String,
	noOfPhotographers: String
});

var chatSchema = new mongoose.Schema({
	firstUser: String,
	secondUser: String,
	chat: Array
});

var photoSchema = new mongoose.Schema({
	user: String,
	photos: Array
});

var User = mongoose.model('user', userSchema, 'user');
var Job = mongoose.model('job', jobSchema, 'job');
var Chat = mongoose.model('chat', chatSchema, 'chat');
var Photo = mongoose.model('photo', photoSchema, 'photo');

module.exports = {
	User : User,
	Job : Job,
	Chat : Chat,
	Photo : Photo
};<commit_msg>chat array<commit_after>var mongoose = require("mongoose");

var userSchema = new mongoose.Schema({
	auth: String,
	id: String,
	username: String,
	displayName: String,
	firstName: String,
	lastName: String,
	email: String,
	link: String,
	picture: String,
	gender: String,
	website: String,
	usertype: String,
	photos: Array,
	workedWith: Array
});

var jobSchema = new mongoose.Schema({
	user: String,
	dateAdded: Date,
	postingAs: String,
	eventName: String,
	dateTime: Date,
	jobDuration: String,
	location: String,
	description: String,
	useOfPhotos: Array,
	dateRequired: String,
	noOfPhotographers: String
});

var chatSchema = new mongoose.Schema({
	firstUser: String,
	secondUser: String,
	users: Array,
	chat: Array
});

var photoSchema = new mongoose.Schema({
	user: String,
	photos: Array
});

var User = mongoose.model('user', userSchema, 'user');
var Job = mongoose.model('job', jobSchema, 'job');
var Chat = mongoose.model('chat', chatSchema, 'chat');
var Photo = mongoose.model('photo', photoSchema, 'photo');

module.exports = {
	User : User,
	Job : Job,
	Chat : Chat,
	Photo : Photo
};<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const fs = require('fs');
const path = require('path');
const package_json = path.resolve('./package.json');
const tsconfig_json = path.resolve('./tsconfig.json');
const webpack_config_js = path.resolve('./webpack.config.js');
const git_ignore_file = path.resolve('./.gitignore');
const eslint_file = path.resolve('./.eslintrc.js');
const index_html = path.resolve('./index.html');
const main_tsx = path.resolve('./src/main.tsx');
const spa_index = path.resolve('./index.html');
const spa_main_tsx = path.resolve('./src/main.tsx');
const spa_layout_tsx = path.resolve('./src/Layout.tsx');
const readme_md = path.resolve('./README.md');
const execSync = require('child_process').execSync;
const program = require('commander');

const dir_src = './src';
const dir_tests = './tests';
const dir_stories = './src/stories'

let show_start = false;
let show_test = false;
let es5 = false;
let no_package = false;

function read(name) {
  return fs.readFileSync(path.resolve(__dirname + '/cli-templates', name), 'utf8');
}

function write(file_name, text, title = ' * Creating', overwrite = false) {
  const file = path.resolve(file_name);
  if (!fs.existsSync(file) || overwrite) {
    process.stdout.write(`${title}: ${file} ... `);
    fs.writeFileSync(
      file,
      text
    );
    process.stdout.write('Done\n');
  } else {
    process.stdout.write(` *  No change made. File exists: ${file}\n`);
  }
}

function init() {
  RegExp.prototype.toJSON = RegExp.prototype.toString;

  if (!fs.existsSync(package_json)) {
    console.log(' * Initializing package.json');
    execSync('npm init -y');
  }

  if (!fs.existsSync(dir_src)) fs.mkdirSync(dir_src);

  const packages_es5 = 'npm install -D apprun@es5 typescript webpack webpack-cli webpack-dev-server ts-loader source-map-loader';
  const packages_es6 = 'npm install -D apprun typescript webpack webpack-cli webpack-dev-server ts-loader source-map-loader';
  console.log(' * Installing packages. This might take a few minutes.');
  if (!no_package) {
    if (!es5) execSync(packages_es5);
    else execSync(packages_es6);
  }
  es5 ?
    write(tsconfig_json, read('tsconfig.es5.json'), ' * Configuring typescript - es5', true) :
    write(tsconfig_json, read('tsconfig.es6.json'), ' * Configuring typescript - es2015', true);

  write(webpack_config_js, read('webpack.config.js'))
  write(index_html, read('index.html'));
  write(main_tsx, read('main.ts_'));
  write(readme_md, read('readme.md'));

  console.log(' * Adding npm scripts');
  const package_info = require(package_json);
  if (!package_info.scripts) package_info["scripts"] = {}
  if (!package_info.scripts['start']) {
    package_info["scripts"]["start"] = 'webpack serve --mode development';
  }
  if (!package_info.scripts['build']) {
    package_info["scripts"]["build"] = 'webpack --mode production';
  }
  if (!package_info.scripts['tsc:watch']) {
    package_info['scripts']['tsc:watch'] = 'tsc -w';
  }
  save_package_json(package_info);
  git_init();
  // jest_init();
  show_start = true;
}

function save_package_json(package_info) {
  fs.writeFileSync(
    package_json,
    JSON.stringify(package_info, null, 2)
  );
}

function git_init() {
  if (!fs.existsSync('.git')) {
    console.log(' * Initializing git');
    execSync('git init');
  } else {
    console.log(' * Skip git init. .git exsits');
  }
  write(git_ignore_file, read('_gitignore'));
}

function component(name) {
  if (!fs.existsSync(dir_src)) fs.mkdirSync(dir_src);
  const fn = path.resolve(dir_src + '/' + name + '.tsx');
  const component_template = read('component.ts_');
  write(fn, component_template.replace(/\#name/g, name),
    `Creating component ${name}`);
  show_start = true;
}

function jest_init() {
  console.log(' * Installing jest');
  execSync('npm i @types/jest jest ts-jest --save-dev');
  const jest_config = {
    "preset": "ts-jest",
  }

  const package_info = require(package_json) || {};
  package_info["jest"] = jest_config

  package_info["scripts"]["test"] = 'jest --watch';
  save_package_json(package_info);
  show_test = true;
}

function lint_init() {
  console.log(' * Installing ESLint');
  execSync('npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin');

  const package_info = require(package_json) || {};
  package_info["scripts"]["lint"] = 'eslint src';
  package_info["scripts"]["lint:fix"] = 'eslint src --fix';
  save_package_json(package_info);

  write(eslint_file, read('_eslintrc.js'));
}

function component_spec(name) {
  if (!fs.existsSync(dir_tests)) fs.mkdirSync(dir_tests);
  const fn = path.resolve(dir_tests + '/' + name + '.spec.ts');
  const test_template = read('spec.ts_');
  write(fn, test_template.replace(/\#name/g, name),
    `Creating component spec ${name}`);
  show_test = true;
}

function component_story(name) {
  if (!fs.existsSync(dir_stories)) fs.mkdirSync(dir_stories);
  const fn = path.resolve(dir_stories + '/' + name + '.stories.tsx');
  const story_template = read('stories.js_');
  write(fn, story_template.replace(/\#name/g, name),
    `Creating component stories ${name}`);
}

function spa() {
  write(spa_index, read('spa_index.html'), 'Creating', true);
  write(spa_main_tsx, read('spa_main.ts_'), 'Creating', true);
  write(spa_layout_tsx, read('Layout.ts_'), 'Creating', true);
  component('Home');
  component('About');
  component('Contact');
  show_start = true;
}

program
  .name('apprun')
  .version('2.27')
  .option('-i, --init', 'Initialize AppRun Project')
  .option('-c, --component <file>', 'Generate AppRun component')
  .option('-g, --git', 'Initialize git repository')
  .option('-j, --jest', 'Install jest')
  .option('-l, --lint', 'Install ESLint')
  .option('-t, --test <file>', 'Generate component spec')
  .option('-o, --story <file>', 'Generate component stories')
  .option('-s, --spa', 'Generate SPA app')
  .option('-5, --es5', 'Use apprun@es5')
  .option('-0, --no_package', 'Don\'t install packages')
  .parse(process.argv);

program._name = 'apprun';

if (!program.init && !program.component && !program.git && !program.jest &&
  !program.test && !program.spa && !program.lint && !program.story) {
  program.outputHelp();
  process.exit()
}

if (program.es5) es5 = true;
if (program.no_package) no_package = true;
if (program.init) init();
if (program.component) component(program.component);
if (program.git) git_init();
if (program.jest) jest_init();
if (program.lint) lint_init();
if (program.test) component_spec(program.test);
if (program.story) component_story(program.story);
if (program.spa) spa();

console.log('\r');
if (show_start) console.log('All done. You can run `npm start` and then navigate to http://localhost:8080 in a browser.');
//if (show_test) console.log('All done. You can run `npm test`.');<commit_msg>fix typo<commit_after>#!/usr/bin/env node

'use strict';

const fs = require('fs');
const path = require('path');
const package_json = path.resolve('./package.json');
const tsconfig_json = path.resolve('./tsconfig.json');
const webpack_config_js = path.resolve('./webpack.config.js');
const git_ignore_file = path.resolve('./.gitignore');
const eslint_file = path.resolve('./.eslintrc.js');
const index_html = path.resolve('./index.html');
const main_tsx = path.resolve('./src/main.tsx');
const spa_index = path.resolve('./index.html');
const spa_main_tsx = path.resolve('./src/main.tsx');
const spa_layout_tsx = path.resolve('./src/Layout.tsx');
const readme_md = path.resolve('./README.md');
const execSync = require('child_process').execSync;
const program = require('commander');

const dir_src = './src';
const dir_tests = './tests';
const dir_stories = './src/stories'

let show_start = false;
let show_test = false;
let es5 = false;
let no_package = false;

function read(name) {
  return fs.readFileSync(path.resolve(__dirname + '/cli-templates', name), 'utf8');
}

function write(file_name, text, title = ' * Creating', overwrite = false) {
  const file = path.resolve(file_name);
  if (!fs.existsSync(file) || overwrite) {
    process.stdout.write(`${title}: ${file} ... `);
    fs.writeFileSync(
      file,
      text
    );
    process.stdout.write('Done\n');
  } else {
    process.stdout.write(` *  No change made. File exists: ${file}\n`);
  }
}

function init() {
  RegExp.prototype.toJSON = RegExp.prototype.toString;

  if (!fs.existsSync(package_json)) {
    console.log(' * Initializing package.json');
    execSync('npm init -y');
  }

  if (!fs.existsSync(dir_src)) fs.mkdirSync(dir_src);

  const packages_es5 = 'npm install -D apprun@es5 typescript webpack webpack-cli webpack-dev-server ts-loader source-map-loader';
  const packages_es6 = 'npm install -D apprun typescript webpack webpack-cli webpack-dev-server ts-loader source-map-loader';
  console.log(' * Installing packages. This might take a few minutes.');
  if (!no_package) {
    es5
      ? execSync(packages_es5)
      : execSync(packages_es6);
  }
  es5
    ? write(tsconfig_json, read('tsconfig.es5.json'), ' * Configuring typescript - es5', true)
    : write(tsconfig_json, read('tsconfig.es6.json'), ' * Configuring typescript - es2015', true);

  write(webpack_config_js, read('webpack.config.js'))
  write(index_html, read('index.html'));
  write(main_tsx, read('main.ts_'));
  write(readme_md, read('readme.md'));

  console.log(' * Adding npm scripts');
  const package_info = require(package_json);
  if (!package_info.scripts) package_info["scripts"] = {}
  if (!package_info.scripts['start']) {
    package_info["scripts"]["start"] = 'webpack serve --mode development';
  }
  if (!package_info.scripts['build']) {
    package_info["scripts"]["build"] = 'webpack --mode production';
  }
  if (!package_info.scripts['tsc:watch']) {
    package_info['scripts']['tsc:watch'] = 'tsc -w';
  }
  save_package_json(package_info);
  git_init();
  // jest_init();
  show_start = true;
}

function save_package_json(package_info) {
  fs.writeFileSync(
    package_json,
    JSON.stringify(package_info, null, 2)
  );
}

function git_init() {
  if (!fs.existsSync('.git')) {
    console.log(' * Initializing git');
    execSync('git init');
  } else {
    console.log(' * Skip git init. .git exsits');
  }
  write(git_ignore_file, read('_gitignore'));
}

function component(name) {
  if (!fs.existsSync(dir_src)) fs.mkdirSync(dir_src);
  const fn = path.resolve(dir_src + '/' + name + '.tsx');
  const component_template = read('component.ts_');
  write(fn, component_template.replace(/\#name/g, name),
    `Creating component ${name}`);
  show_start = true;
}

function jest_init() {
  console.log(' * Installing jest');
  execSync('npm i @types/jest jest ts-jest --save-dev');
  const jest_config = {
    "preset": "ts-jest",
  }

  const package_info = require(package_json) || {};
  package_info["jest"] = jest_config

  package_info["scripts"]["test"] = 'jest --watch';
  save_package_json(package_info);
  show_test = true;
}

function lint_init() {
  console.log(' * Installing ESLint');
  execSync('npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin');

  const package_info = require(package_json) || {};
  package_info["scripts"]["lint"] = 'eslint src';
  package_info["scripts"]["lint:fix"] = 'eslint src --fix';
  save_package_json(package_info);

  write(eslint_file, read('_eslintrc.js'));
}

function component_spec(name) {
  if (!fs.existsSync(dir_tests)) fs.mkdirSync(dir_tests);
  const fn = path.resolve(dir_tests + '/' + name + '.spec.ts');
  const test_template = read('spec.ts_');
  write(fn, test_template.replace(/\#name/g, name),
    `Creating component spec ${name}`);
  show_test = true;
}

function component_story(name) {
  if (!fs.existsSync(dir_stories)) fs.mkdirSync(dir_stories);
  const fn = path.resolve(dir_stories + '/' + name + '.stories.tsx');
  const story_template = read('stories.js_');
  write(fn, story_template.replace(/\#name/g, name),
    `Creating component stories ${name}`);
}

function spa() {
  write(spa_index, read('spa_index.html'), 'Creating', true);
  write(spa_main_tsx, read('spa_main.ts_'), 'Creating', true);
  write(spa_layout_tsx, read('Layout.ts_'), 'Creating', true);
  component('Home');
  component('About');
  component('Contact');
  show_start = true;
}

program
  .name('apprun')
  .version('2.27')
  .option('-i, --init', 'Initialize AppRun Project')
  .option('-c, --component <file>', 'Generate AppRun component')
  .option('-g, --git', 'Initialize git repository')
  .option('-j, --jest', 'Install jest')
  .option('-l, --lint', 'Install ESLint')
  .option('-t, --test <file>', 'Generate component spec')
  .option('-o, --story <file>', 'Generate component stories')
  .option('-s, --spa', 'Generate SPA app')
  .option('-5, --es5', 'Use apprun@es5')
  .option('-0, --no_package', 'Don\'t install packages')
  .parse(process.argv);

program._name = 'apprun';

if (!program.init && !program.component && !program.git && !program.jest &&
  !program.test && !program.spa && !program.lint && !program.story) {
  program.outputHelp();
  process.exit()
}

if (program.es5) es5 = true;
if (program.no_package) no_package = true;
if (program.init) init();
if (program.component) component(program.component);
if (program.git) git_init();
if (program.jest) jest_init();
if (program.lint) lint_init();
if (program.test) component_spec(program.test);
if (program.story) component_story(program.story);
if (program.spa) spa();

console.log('\r');
if (show_start) console.log('All done. You can run `npm start` and then navigate to http://localhost:8080 in a browser.');
//if (show_test) console.log('All done. You can run `npm test`.');<|endoftext|>


<commit_before>// test/lib/TempDir.js
//

'use strict';

var cmds = require('../../lib/commands');

var fs = require('fs');
var path = require('path');
var spawnSync = require('child_process').spawnSync;

var mkdirp = require('mkdirp');
var rimraf = require('rimraf');

var TempDir = {
  tmpLocation: null,

  prepare: function () {
    mkdirp.sync(this.tmpLocation);
  },

  clean: function () {
    rimraf.sync(this.tmpLocation);
  },

  getPath: function (name) {
    return path.join(this.tmpLocation, name);
  },

  read: function (name) {
    return fs.readFileSync(this.getPath(name), 'utf8');
  },

  readJson: function (name) {
    return JSON.parse(this.read(name));
  },

  exists: function (name) {
    return fs.accessSync(path.join(this.tmpLocation, name), fs.F_OK);
  },

  runCmd: function (cmd, argv) {
    argv = [cmd].concat(argv);
    return cmds[cmd](argv, this.tmpLocation);
  },

  collider: function (args) {
    args = args || [];
    return spawnSync('collider', args, { cwd: this.tmpLocation });
  },
};

module.exports = TempDir;
<commit_msg>Update TempDir.exists to return a boolean<commit_after>// test/lib/TempDir.js
//

'use strict';

var cmds = require('../../lib/commands');

var fs = require('fs');
var path = require('path');
var spawnSync = require('child_process').spawnSync;

var mkdirp = require('mkdirp');
var rimraf = require('rimraf');

var TempDir = {
  tmpLocation: null,

  prepare: function () {
    mkdirp.sync(this.tmpLocation);
  },

  clean: function () {
    rimraf.sync(this.tmpLocation);
  },

  getPath: function (name) {
    return path.join(this.tmpLocation, name);
  },

  read: function (name) {
    return fs.readFileSync(this.getPath(name), 'utf8');
  },

  readJson: function (name) {
    return JSON.parse(this.read(name));
  },

  exists: function (name) {
    return fs.accessSync(path.join(this.tmpLocation, name), fs.F_OK) ? false : true;
  },

  runCmd: function (cmd, argv) {
    argv = [cmd].concat(argv);
    return cmds[cmd](argv, this.tmpLocation);
  },

  collider: function (args) {
    args = args || [];
    return spawnSync('collider', args, { cwd: this.tmpLocation });
  },
};

module.exports = TempDir;
<|endoftext|>


<commit_before>/* ************************************************************************

    License: MIT Licence

    Description:
        Main AppStorm.JS functionality, create some needed system to help plugin or user

************************************************************************ */

/*!
 * @private
*/
;

/*
 * Bind AppStorm.JS to lodash.
 * Note: in node module, we need to deep clone it (does not seems to be
 * needed for chrome/firefox/others version)
*/
window.appstorm = window.a = _.cloneDeep(_.noConflict());

(function(a) {
    /**
     * Avoid namespace conflict.
     *
     * @return {AppStorm.JS}                The main a object from AppStorm.JS
    */
    a.noConflict = function() {
        return this;
    };
})(window.appstorm);

/**
 * The core url (for vendor loading)
 *
 * @property url
 * @type String
*/
a.url = '';

/**
 * Change the function initial scope for given one
 *
 * @method scope
 *
 * @param fct {Function}                    The function to bind scope
 * @param scope {Object}                    The object scope to link
 * @return {Function}                       Intermediate function with scope
 *                                          binding
*/
a.scope = function(fct, scope) {
    return function() {
        return fct.apply(scope, arguments);
    };
};

/**
 * Get the existing stack trace
 *
 * @method getStackTrace
 *
 * @return {String}                         Stack trace
*/
a.getStackTrace = function() {
    var err = new Error();
    return err.stack;
};

/**
 * Test if the element is null or undefined
 *
 * @method isNone
 *
 * @param obj {Object}                      The element to test
 * @return {Boolean}                        True if element is null/undefined
 *                                          False in other cases
*/
a.isNone = function(obj) {
    return (a.isNull(obj) || a.isUndefined(obj));
};

/**
 * Test if the element is a non-null object type
 *
 * @method isTrueObject
 *
 * @param obj {Object}                      The element to test
 * @return {Boolean}                        True if it's an object, false if
 *                                          it's a null value, or not an object
*/
a.isTrueObject = function(obj) {
    return (typeof(obj) === 'object' && !a.isNone(obj));
};

/**
 * Allow trimming string value
 *
 * @method trim
 *
 * @param str {String}                      The value to trim
 * @return {String}                         The trimmed value
*/
a.trim = function(str) {
    // We allow both native and custom trim
    if (!String.prototype.trim) {
        return str.replace(/^\s+|\s+$/g, '');
    } else {
        return str.trim();
    }
};

/**
 * Make the first letter of given string, uppercase.
 *
 * @method firstLetterUpperCase
 *
 * @param str {String}                      The string to apply transformation
 * @param prefix {String}                   A prefix to apply aftre transform
 * @return {String}                         The string with first letter in
 *                                          uppercase
*/
a.firstLetterUppercase = function(str, prefix) {
    prefix = prefix || '';
    return prefix + str.charAt(0).toUpperCase() + str.slice(1);
};

/**
* Create a deep copy (used internally)
* FROM : http://www.xenoveritas.org/blog/xeno/the-correct-way-to-clone-javascript-arrays
* Credits to them ! Little bug corrected :p
*
* @method clone
*
* @param obj {Object}                       A state object
* @return {Object}                          A new state object
*/
a.deepClone = function(obj) {
    // The deep clone only take care of object, and not function
    if (a.isTrueObject(obj) && !a.isFunction(obj)) {
        // Array cloning
        if(a.isArray(obj)) {
            var l = obj.length,
                y = new Array(l);
            for(var i = 0; i < l; ++i) {
                y[i] = a.deepClone(obj[i]);
            }
            return y;

        // Object cloning
        } else {
            var r = {};
            if(a.isFunction(obj.constructor)) {
                r = new obj.constructor();
            }
            // Bug : json object does not have prototype
            if(a.isTrueObject(obj.prototype)) {
                r.prototype = obj.prototype;
            }
            for(var k in obj) {
                r[k] = a.deepClone(obj[k]);
            }
            return r;
        }
    }
    return obj;
};

/**
 * Get the difference between objects.
 *
 * @method
 *
 * @param obj1 {Object}                     The object initial to retrieve
 *                                          difference from
 * @param obj2 {Object}                     The second object to check
 *                                          difference from
 * @return {Object}                         The result-free object
*/
a.differenceObject = function(obj1, obj2) {
    var keys = a.difference(a.keys(obj1), a.keys(obj2)),
        result = {};

    a.each(keys, function(key) {
        result[key] = this[key];
    }, obj1);

    return result;
};

/**
 * Extend an object with child properties (underscore.js like)
 *
 * @method extend
 *
 * @param object {Object}                   The element to extend with other
 *                                          properties
 * @param source {Object}                   The source object to take
 *                                          properties from
 * @return {Object}                         A combined object
*/
a.extend = function(object, source, guard) {
    if (!object) {
        return object;
    }
    var args = arguments,
        argsIndex = 0,
        argsLength = args.length,
        type = typeof guard;

    if ((type == 'number' || type == 'string') && args[3] &&
            args[3][guard] === source) {
        argsLength = 2;
    }
    while (++argsIndex < argsLength) {
        source = args[argsIndex];
        if (source) {
            for (var key in source) {
                object[key] = source[key];
            }
        }
    }
    return object;
};

/**
 * Alias for Watch.JS
 *
 * @method watch
 * @see https://github.com/melanke/Watch.JS/
 *
 * @param                                   See Watch.JS documentation
*/
a.watch = function() {
    WatchJS.watch.apply(this, arguments);
};

/**
 * Alias for Watch.JS
 *
 * @method unwatch
 * @see https://github.com/melanke/Watch.JS/
 *
 * @param                                   See Watch.JS documentation
*/
a.unwatch = function() {
    WatchJS.unwatch.apply(this, arguments);
};

/**
 * Define the default ajax options to send on every request.
 * At any time, by providing good options, you can override this content
 * on a single ajax request.
 *
 * @method setDefaultAjaxOptions
 *
 * @param options {Object}                  The default options to set
*/
a.setDefaultAjaxOptions = function(options) {
    if(a.isTrueObject(options)) {
        a.mem.set('app.ajax.default', options);
    }
};

/**
 * Get the default ajax options currently stored
 * (and used by every ajax request)
 *
 * @method getDefaultAjaxOptions
 *
 * @return {Object}                         The default ajax options setted
*/
a.getDefaultAjaxOptions = function() {
    return a.mem.get('app.ajax.default') || {};
};

/**
 * Define an ajax template to use for the given request
 *
 * @method setTemplateAjaxOptions
 *
 * @param name {String}                     The template name to define
 * @param options {Object}                  The options linked to template
*/
a.setTemplateAjaxOptions = function(name, options) {
    if(name && a.isTrueObject(options)) {
        a.mem.set('app.ajax.template.' + name, options);
    }
};

/**
 * Get an existing template rearding it's name
 *
 * @method getTemplateAjaxOptions
 *
 * @param name {String}                     The template name to retrieve
 * @return {Object | null}                  The resulting object content
*/
a.getTemplateAjaxOptions = function(name) {
    return a.mem.get('app.ajax.template.' + name);
};

/**
 * Set a before action to perform on every ajax request using it
 *
 * @method setAjaxBefore
 *
 * @param name {String}                     The name to use for recall
 * @param fct {Function | null}             The linked function to use
*/
a.setAjaxBefore = function(name, fct) {
    if(name && a.isFunction(fct)) {
        a.mem.set('app.ajax.before.' + name, fct);
    }
};

/**
 * Get an existing ajax before function, or null if nothing is found
 *
 * @method getAjaxBefore
 *
 * @param name {String}                     The name previously stored using
 *                                          setAjaxBefore
 * @return {Function | null}                The function if found, null in
 *                                          other cases
*/
a.getAjaxBefore = function(name) {
    return a.mem.get('app.ajax.before.' + name) || null;
};

/**
 * Set an after action to perform on every ajax request using it
 *
 * @method setAjaxAfter
 *
 * @param name {String}                     The name to use for recall
 * @param fct {Function | null}             The linked function to use
*/
a.setAjaxAfter = function(name, fct) {
    if(name && a.isFunction(fct)) {
        a.mem.set('app.ajax.after.' + name, fct);
    }
};

/**
 * Get an existing ajax after function, or null if nothing is found
 *
 * @method getAjaxAfter
 *
 * @param name {String}                     The name previously stored using
 *                                          setAjaxAfter
 * @return {Function | null}                The function if found, null in
 *                                          other cases
*/
a.getAjaxAfter = function(name) {
    return a.mem.get('app.ajax.after.' + name) || null;
};

/*
 * Check AppStorm.JS source url
*/
(function() {
    // Detecting base url of AppStorm.JS
    var me = document.getElementById('a-core');
    if(me && !a.isNone(me.src)) {
        a.url = me.src.replace(new RegExp('/[^/]*$'), '/');
    }
}());

/*
------------------------------
  HANDLEBARS HELPERS
------------------------------
*/
(function() {
    // From: http://blog.teamtreehouse.com/handlebars-js-part-3-tips-and-tricks
    Handlebars.registerHelper('debug', function(optionalValue) {
        a.console.log('===== CONTEXT ======');
        a.console.log(this);

        if(!a.isUndefined(optionalValue)) {
            a.console.log('====== VALUE =======');
            a.console.log(optionalValue);
        }
    });

    // Try to count elements
    Handlebars.registerHelper('count', function(value) {
        a.console.log('=== DEBUG COUNT ====');
        if(a.isUndefined(value.length)) {
            a.console.log('Length is not defined for value');
            a.console.log(value);
        } else {
            a.console.log(value.length);
        }
    });
})();<commit_msg>Adding URL sanitize<commit_after>/* ************************************************************************

    License: MIT Licence

    Description:
        Main AppStorm.JS functionality, create some needed system to help plugin or user

************************************************************************ */

/*!
 * @private
*/
;

/*
 * Bind AppStorm.JS to lodash.
 * Note: in node module, we need to deep clone it (does not seems to be
 * needed for chrome/firefox/others version)
*/
window.appstorm = window.a = _.cloneDeep(_.noConflict());

(function(a) {
    /**
     * Avoid namespace conflict.
     *
     * @return {AppStorm.JS}                The main a object from AppStorm.JS
    */
    a.noConflict = function() {
        return this;
    };
})(window.appstorm);

/**
 * The core url (for vendor loading)
 *
 * @property url
 * @type String
*/
a.url = '';

/**
 * Change the function initial scope for given one
 *
 * @method scope
 *
 * @param fct {Function}                    The function to bind scope
 * @param scope {Object}                    The object scope to link
 * @return {Function}                       Intermediate function with scope
 *                                          binding
*/
a.scope = function(fct, scope) {
    return function() {
        return fct.apply(scope, arguments);
    };
};

/**
 * Get the existing stack trace
 *
 * @method getStackTrace
 *
 * @return {String}                         Stack trace
*/
a.getStackTrace = function() {
    var err = new Error();
    return err.stack;
};

/**
 * Test if the element is null or undefined
 *
 * @method isNone
 *
 * @param obj {Object}                      The element to test
 * @return {Boolean}                        True if element is null/undefined
 *                                          False in other cases
*/
a.isNone = function(obj) {
    return (a.isNull(obj) || a.isUndefined(obj));
};

/**
 * Test if the element is a non-null object type
 *
 * @method isTrueObject
 *
 * @param obj {Object}                      The element to test
 * @return {Boolean}                        True if it's an object, false if
 *                                          it's a null value, or not an object
*/
a.isTrueObject = function(obj) {
    return (typeof(obj) === 'object' && !a.isNone(obj));
};

/**
 * Allow trimming string value
 *
 * @method trim
 *
 * @param str {String}                      The value to trim
 * @return {String}                         The trimmed value
*/
a.trim = function(str) {
    // We allow both native and custom trim
    if (!String.prototype.trim) {
        return str.replace(/^\s+|\s+$/g, '');
    } else {
        return str.trim();
    }
};

/**
 * Make the first letter of given string, uppercase.
 *
 * @method firstLetterUpperCase
 *
 * @param str {String}                      The string to apply transformation
 * @param prefix {String}                   A prefix to apply aftre transform
 * @return {String}                         The string with first letter in
 *                                          uppercase
*/
a.firstLetterUppercase = function(str, prefix) {
    prefix = prefix || '';
    return prefix + str.charAt(0).toUpperCase() + str.slice(1);
};

/**
* Create a deep copy (used internally)
* FROM : http://www.xenoveritas.org/blog/xeno/the-correct-way-to-clone-javascript-arrays
* Credits to them ! Little bug corrected :p
*
* @method clone
*
* @param obj {Object}                       A state object
* @return {Object}                          A new state object
*/
a.deepClone = function(obj) {
    // The deep clone only take care of object, and not function
    if (a.isTrueObject(obj) && !a.isFunction(obj)) {
        // Array cloning
        if(a.isArray(obj)) {
            var l = obj.length,
                y = new Array(l);
            for(var i = 0; i < l; ++i) {
                y[i] = a.deepClone(obj[i]);
            }
            return y;

        // Object cloning
        } else {
            var r = {};
            if(a.isFunction(obj.constructor)) {
                r = new obj.constructor();
            }
            // Bug : json object does not have prototype
            if(a.isTrueObject(obj.prototype)) {
                r.prototype = obj.prototype;
            }
            for(var k in obj) {
                r[k] = a.deepClone(obj[k]);
            }
            return r;
        }
    }
    return obj;
};

/**
 * Get the difference between objects.
 *
 * @method
 *
 * @param obj1 {Object}                     The object initial to retrieve
 *                                          difference from
 * @param obj2 {Object}                     The second object to check
 *                                          difference from
 * @return {Object}                         The result-free object
*/
a.differenceObject = function(obj1, obj2) {
    var keys = a.difference(a.keys(obj1), a.keys(obj2)),
        result = {};

    a.each(keys, function(key) {
        result[key] = this[key];
    }, obj1);

    return result;
};

/**
 * Extend an object with child properties (underscore.js like)
 *
 * @method extend
 *
 * @param object {Object}                   The element to extend with other
 *                                          properties
 * @param source {Object}                   The source object to take
 *                                          properties from
 * @return {Object}                         A combined object
*/
a.extend = function(object, source, guard) {
    if (!object) {
        return object;
    }
    var args = arguments,
        argsIndex = 0,
        argsLength = args.length,
        type = typeof guard;

    if ((type == 'number' || type == 'string') && args[3] &&
            args[3][guard] === source) {
        argsLength = 2;
    }
    while (++argsIndex < argsLength) {
        source = args[argsIndex];
        if (source) {
            for (var key in source) {
                object[key] = source[key];
            }
        }
    }
    return object;
};

/**
 * Alias for Watch.JS
 *
 * @method watch
 * @see https://github.com/melanke/Watch.JS/
 *
 * @param                                   See Watch.JS documentation
*/
a.watch = function() {
    WatchJS.watch.apply(this, arguments);
};

/**
 * Alias for Watch.JS
 *
 * @method unwatch
 * @see https://github.com/melanke/Watch.JS/
 *
 * @param                                   See Watch.JS documentation
*/
a.unwatch = function() {
    WatchJS.unwatch.apply(this, arguments);
};

/**
 * Sanitize a URL. Mostly usefull internally to avoid loading twice the
 * same url because of stupid hack like this ./hello/../hello.
 * FROM: http://jsperf.com/normalize-path
 *
 * @param {String} url                      The url to sanitize
 * @return {String}                         The url sanitize
*/
a.sanitize = function(url) {
    var parts       = url.split('/'),
        directories = [],
        prev;

    for (var i = 0, l = parts.length - 1; i <= l; i++) {
        var directory = parts[i];

        // if it's blank, but it's not the first thing, and not the
        // last thing, skip it.
        if (directory === '' && i !== 0 && i !== l) {
            continue;
        }

        // if it's a dot, and there was some previous dir already, then
        // skip it.
        if (directory === '.' && typeof prev !== 'undefined') {
            continue;
        }

        // if it starts with "", and is a . or .., then skip it.
        if (directories.length === 1 && directories[0] === '' &&
                (directory === '.' || directory === '..')) {
            continue;
        }

        if (directory === '..' && directories.length && prev !== '..' &&
                prev !== '.' && typeof prev !== 'undefined' &&
                prev !== '') {
            directories.pop();
            prev = directories.slice(-1)[0]
        } else {
            if (prev === '.') {
                directories.pop();
            }
            directories.push(directory);
            prev = directory;
        }
    }

    var result = directories.join('/');

    // It may contains a first char '/'
    if (result.length > 0 && result[0] === '/') {
        result = result.substr(1);
    }

    return result;
};

/**
 * Define the default ajax options to send on every request.
 * At any time, by providing good options, you can override this content
 * on a single ajax request.
 *
 * @method setDefaultAjaxOptions
 *
 * @param options {Object}                  The default options to set
*/
a.setDefaultAjaxOptions = function(options) {
    if(a.isTrueObject(options)) {
        a.mem.set('app.ajax.default', options);
    }
};

/**
 * Get the default ajax options currently stored
 * (and used by every ajax request)
 *
 * @method getDefaultAjaxOptions
 *
 * @return {Object}                         The default ajax options setted
*/
a.getDefaultAjaxOptions = function() {
    return a.mem.get('app.ajax.default') || {};
};

/**
 * Define an ajax template to use for the given request
 *
 * @method setTemplateAjaxOptions
 *
 * @param name {String}                     The template name to define
 * @param options {Object}                  The options linked to template
*/
a.setTemplateAjaxOptions = function(name, options) {
    if(name && a.isTrueObject(options)) {
        a.mem.set('app.ajax.template.' + name, options);
    }
};

/**
 * Get an existing template rearding it's name
 *
 * @method getTemplateAjaxOptions
 *
 * @param name {String}                     The template name to retrieve
 * @return {Object | null}                  The resulting object content
*/
a.getTemplateAjaxOptions = function(name) {
    return a.mem.get('app.ajax.template.' + name);
};

/**
 * Set a before action to perform on every ajax request using it
 *
 * @method setAjaxBefore
 *
 * @param name {String}                     The name to use for recall
 * @param fct {Function | null}             The linked function to use
*/
a.setAjaxBefore = function(name, fct) {
    if(name && a.isFunction(fct)) {
        a.mem.set('app.ajax.before.' + name, fct);
    }
};

/**
 * Get an existing ajax before function, or null if nothing is found
 *
 * @method getAjaxBefore
 *
 * @param name {String}                     The name previously stored using
 *                                          setAjaxBefore
 * @return {Function | null}                The function if found, null in
 *                                          other cases
*/
a.getAjaxBefore = function(name) {
    return a.mem.get('app.ajax.before.' + name) || null;
};

/**
 * Set an after action to perform on every ajax request using it
 *
 * @method setAjaxAfter
 *
 * @param name {String}                     The name to use for recall
 * @param fct {Function | null}             The linked function to use
*/
a.setAjaxAfter = function(name, fct) {
    if(name && a.isFunction(fct)) {
        a.mem.set('app.ajax.after.' + name, fct);
    }
};

/**
 * Get an existing ajax after function, or null if nothing is found
 *
 * @method getAjaxAfter
 *
 * @param name {String}                     The name previously stored using
 *                                          setAjaxAfter
 * @return {Function | null}                The function if found, null in
 *                                          other cases
*/
a.getAjaxAfter = function(name) {
    return a.mem.get('app.ajax.after.' + name) || null;
};

/*
 * Check AppStorm.JS source url
*/
(function() {
    // Detecting base url of AppStorm.JS
    var me = document.getElementById('a-core');
    if(me && !a.isNone(me.src)) {
        a.url = me.src.replace(new RegExp('/[^/]*$'), '/');
    }
}());

/*
------------------------------
  HANDLEBARS HELPERS
------------------------------
*/
(function() {
    // From: http://blog.teamtreehouse.com/handlebars-js-part-3-tips-and-tricks
    Handlebars.registerHelper('debug', function(optionalValue) {
        a.console.log('===== CONTEXT ======');
        a.console.log(this);

        if(!a.isUndefined(optionalValue)) {
            a.console.log('====== VALUE =======');
            a.console.log(optionalValue);
        }
    });

    // Try to count elements
    Handlebars.registerHelper('count', function(value) {
        a.console.log('=== DEBUG COUNT ====');
        if(a.isUndefined(value.length)) {
            a.console.log('Length is not defined for value');
            a.console.log(value);
        } else {
            a.console.log(value.length);
        }
    });
})();<|endoftext|>