<commit_before>((window) => {
  const div = d3.selectAll('#whisker-graph');

  function showTooltip(box, name, stats) {
    div.selectAll('.tooltip-back')
      .style('display', 'block');

    div.selectAll('.tooltip-text-title')
      .text(`${name} year${name[0] === '<' || name[0] === '1' ? '' : 's'}`);

    div.selectAll('.tooltip-text-min')
      .text(`min = ${stats.min.toFixed(2)};`)

    div.selectAll('.tooltip-text-mins')
      .text(`5% = ${stats.quantiles[5].toFixed(2)}; 25% = ${stats.quantiles[25].toFixed(2)};`)

    div.selectAll('.tooltip-text-median')
      .text(`50% = ${stats.quantiles[50].toFixed(2)};`)

    div.selectAll('.tooltip-text-maxs')
      .text(`75% = ${stats.quantiles[75].toFixed(2)}; 95% = ${stats.quantiles[95].toFixed(2)};`)

    div.selectAll('.tooltip-text-max')
      .text(`max = ${stats.max.toFixed(2)};`)

    div.selectAll('.tooltip')
      .style('display', 'block');

    box.selectAll('rect')
      .style('fill', '#d1ccf3');
  }

  function hideTooltip(box) {
    div.selectAll('.tooltip-back')
      .style('display', 'none');

    div.selectAll('.tooltip')
      .style('display', 'none');

    box.selectAll('rect')
      .style('fill', 'none');
  }

  // Salary whisker graph graph object
  const WhiskerGraph = {
    init(years, prop, stats) {
      const margin = { top: 10, right: 0, bottom: 20, left: 40 };
      const width = 480;
      const height = width * 0.6;

      const mainColor = '#333';
      const accentColor = '#c85000';
      const radius = 2;
      const lineWidth = 5;
      const textHeight = 10;

      div.selectAll('svg').remove();

      const svg = div
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom);

      const g = svg
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

      const size = stats.max - stats.min;

      const x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .2)
        .domain(years.map(function(d) { return d.name; }));
      const y = d3.scale.linear()
        .range([height, 0])
        .domain([stats.min - size * 0.1, stats.max + size * 0.1]);

      const maxBoxWidth = x.rangeBand();
      const boxWidth = 18;
      const shift = (maxBoxWidth - boxWidth) / 2;

      const xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom');

      const yAxis = d3.svg.axis()
        .scale(y)
        .orient('left')
        .ticks(10)
        .tickFormat((d) => d / 1000);

      g.selectAll('#whisker .box')
        .data(years)
        .enter()
        .append('g')
        .each(function(d) {
          const data = d.stats[prop];
          if (!data) { return; }

          const box = d3.select(this);
          const cx = shift + x(d.name) + boxWidth / 2;

          const max = y(data.min);
          const quant95 = y(data.quantiles[5]);
          const quant75 = y(data.quantiles[25]);
          const quant50 = y(data.quantiles[50]);
          const quant25 = y(data.quantiles[75]);
          const quant5 = y(data.quantiles[95]);
          const min = y(data.max);

          // box - quantiles from 25 to 75
          box.append('rect')
            .style('fill', 'none')
            .style('stroke', mainColor)
            .attr('x', cx - boxWidth / 2)
            .attr('y', quant25)
            .attr('width', boxWidth)
            .attr('height', quant75 - quant25);

          // horizontal median line
          box.append('line')
            .style('stroke', accentColor)
            .style('stroke-width', 2)
            .attr('x1', cx - boxWidth / 2)
            .attr('y1', quant50)
            .attr('x2', cx + boxWidth / 2)
            .attr('y2', quant50);

          // lines between 25 and 75 quantiles and 5 and 95 quantiles with points
          if (quant5 < quant25) {
            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx)
              .attr('y1', quant5)
              .attr('x2', cx)
              .attr('y2', quant25);

            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx - lineWidth)
              .attr('y1', quant5)
              .attr('x2', cx + lineWidth)
              .attr('y2', quant5);
          }
          if (quant95 > quant75) {
            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx)
              .attr('y1', quant95)
              .attr('x2', cx)
              .attr('y2', quant75);

            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx - lineWidth)
              .attr('y1', quant95)
              .attr('x2', cx + lineWidth)
              .attr('y2', quant95);
          }

          // min and max - as circles
          if (min < quant5) {
            box.append('circle')
              .style('fill', 'none')
              .style('stroke', mainColor)
              .attr('cx', cx)
              .attr('cy', min)
              .attr('r', radius);
          }
          if (max > quant95) {
            box.append('circle')
              .style('fill', 'none')
              .style('stroke', mainColor)
              .attr('cx', cx)
              .attr('cy', max)
              .attr('r', radius);
          }

          box.on('mousemove', function(d) {
            showTooltip(box, d.name, data);
          })
          .on('mouseleave', function() {
            hideTooltip(box);
          });
        });

      // add two axes
      g.append('g')
        .attr('class', 'axis')
        .attr('transform', `translate(0,${height})`)
        .call(xAxis);

      g.append('g')
        .attr('class', 'axis')
        .call(yAxis)
        .append('text')
        .attr('transform', 'rotate(-90)');

      // add background for tooltip
      g.append('rect')
        .attr('class', 'tooltip-back')
        .style('display', 'none')
        .attr('x', shift * 2)
        .attr('y', 0)
        .attr('width', 220)
        .attr('height', 110);

      // add tooltip text
      const tooltip = g
        .append('g')
        .attr('class', 'tooltip')
        .style('display', 'none');
      const x0 = shift * 3;
      const y0 = shift + textHeight;

      tooltip.append('text')
        .attr('class', 'tooltip-text-title')
        .attr('x', x0)
        .attr('y', y0);

      const tooltipStats = tooltip
        .append('text')
        .attr('x', x0)
        .attr('y', y0 * 2 + 2)

      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-min')
        .attr('x', x0);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-mins')
        .attr('x', x0)
        .attr('dy', textHeight + shift);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-median')
        .attr('x', x0)
        .attr('dy', textHeight + shift);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-maxs')
        .attr('x', x0)
        .attr('dy', textHeight + shift);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-max')
        .attr('x', x0)
        .attr('dy', textHeight + shift);
    },
  };

  // Expose API globally.
  window.DS = Object.assign({}, window.DS || {}, {
    WhiskerGraph
  });
})(window);
<commit_msg>Fix tooltip<commit_after>((window) => {
  const div = d3.selectAll('#whisker-graph');

  function showTooltip(box, name, stats) {
    div.selectAll('.tooltip-back')
      .style('display', 'block');

    div.selectAll('.tooltip-text-title')
      .text(`${name} year${name[0] === '<' || name[0] === '1' ? '' : 's'}`);

    div.selectAll('.tooltip-text-min')
      .text(`min = ${stats.min.toFixed(2)};`)

    div.selectAll('.tooltip-text-mins')
      .text(`5% = ${stats.quantiles[5].toFixed(2)}; 25% = ${stats.quantiles[25].toFixed(2)};`)

    div.selectAll('.tooltip-text-median')
      .text(`50% = ${stats.quantiles[50].toFixed(2)};`)

    div.selectAll('.tooltip-text-maxs')
      .text(`75% = ${stats.quantiles[75].toFixed(2)}; 95% = ${stats.quantiles[95].toFixed(2)};`)

    div.selectAll('.tooltip-text-max')
      .text(`max = ${stats.max.toFixed(2)};`)

    div.selectAll('.tooltip')
      .style('display', 'block');

    box.selectAll('rect')
      .style('fill', '#d1ccf3');
  }

  function hideTooltip(box) {
    div.selectAll('.tooltip-back')
      .style('display', 'none');

    div.selectAll('.tooltip')
      .style('display', 'none');

    box.selectAll('rect')
      .style('fill', 'none');
  }

  // Salary whisker graph graph object
  const WhiskerGraph = {
    init(years, prop, stats) {
      const margin = { top: 10, right: 0, bottom: 20, left: 40 };
      const width = 480;
      const height = width * 0.6;

      const mainColor = '#333';
      const accentColor = '#c85000';
      const radius = 2;
      const lineWidth = 5;
      const textHeight = 10;

      div.selectAll('svg').remove();

      const svg = div
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom);

      const g = svg
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

      const size = stats.max - stats.min;

      const x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .2)
        .domain(years.map(function(d) { return d.name; }));
      const y = d3.scale.linear()
        .range([height, 0])
        .domain([stats.min - size * 0.1, stats.max + size * 0.1]);

      const maxBoxWidth = x.rangeBand();
      const boxWidth = 18;
      const shift = (maxBoxWidth - boxWidth) / 2;

      const xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom');

      const yAxis = d3.svg.axis()
        .scale(y)
        .orient('left')
        .ticks(10)
        .tickFormat((d) => d / 1000);

      g.selectAll('#whisker .box')
        .data(years)
        .enter()
        .append('g')
        .each(function(d) {
          const data = d.stats[prop];
          if (!data) { return; }

          const box = d3.select(this);
          const cx = shift + x(d.name) + boxWidth / 2;

          const max = y(data.min);
          const quant95 = y(data.quantiles[5]);
          const quant75 = y(data.quantiles[25]);
          const quant50 = y(data.quantiles[50]);
          const quant25 = y(data.quantiles[75]);
          const quant5 = y(data.quantiles[95]);
          const min = y(data.max);

          // box - quantiles from 25 to 75
          box.append('rect')
            .style('fill', 'none')
            .style('stroke', mainColor)
            .attr('x', cx - boxWidth / 2)
            .attr('y', quant25)
            .attr('width', boxWidth)
            .attr('height', quant75 - quant25);

          // horizontal median line
          box.append('line')
            .style('stroke', accentColor)
            .style('stroke-width', 2)
            .attr('x1', cx - boxWidth / 2)
            .attr('y1', quant50)
            .attr('x2', cx + boxWidth / 2)
            .attr('y2', quant50);

          // lines between 25 and 75 quantiles and 5 and 95 quantiles with points
          if (quant5 < quant25) {
            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx)
              .attr('y1', quant5)
              .attr('x2', cx)
              .attr('y2', quant25);

            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx - lineWidth)
              .attr('y1', quant5)
              .attr('x2', cx + lineWidth)
              .attr('y2', quant5);
          }
          if (quant95 > quant75) {
            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx)
              .attr('y1', quant95)
              .attr('x2', cx)
              .attr('y2', quant75);

            box.append('line')
              .style('stroke', mainColor)
              .attr('x1', cx - lineWidth)
              .attr('y1', quant95)
              .attr('x2', cx + lineWidth)
              .attr('y2', quant95);
          }

          // min and max - as circles
          if (min < quant5) {
            box.append('circle')
              .style('fill', 'none')
              .style('stroke', mainColor)
              .attr('cx', cx)
              .attr('cy', min)
              .attr('r', radius);
          }
          if (max > quant95) {
            box.append('circle')
              .style('fill', 'none')
              .style('stroke', mainColor)
              .attr('cx', cx)
              .attr('cy', max)
              .attr('r', radius);
          }

          box.on('mousemove', function(d) {
            showTooltip(box, d.name, data);
          })
          .on('mouseleave', function() {
            hideTooltip(box);
          });
        });

      // add two axes
      g.append('g')
        .attr('class', 'axis')
        .attr('transform', `translate(0,${height})`)
        .call(xAxis);

      g.append('g')
        .attr('class', 'axis')
        .call(yAxis)
        .append('text')
        .attr('transform', 'rotate(-90)');

      // add background for tooltip
      const shiftT = 6;
      g.append('rect')
        .attr('class', 'tooltip-back')
        .style('display', 'none')
        .attr('x', shiftT * 2)
        .attr('y', 0)
        .attr('width', 220)
        .attr('height', 108);

      // add tooltip text
      const tooltip = g
        .append('g')
        .attr('class', 'tooltip')
        .style('display', 'none');
      const x0 = shiftT * 3;
      const y0 = shiftT + textHeight;

      tooltip.append('text')
        .attr('class', 'tooltip-text-title')
        .attr('x', x0)
        .attr('y', y0);

      const tooltipStats = tooltip
        .append('text')
        .attr('x', x0)
        .attr('y', y0 * 2 + 2)

      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-min')
        .attr('x', x0);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-mins')
        .attr('x', x0)
        .attr('dy', textHeight + shiftT);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-median')
        .attr('x', x0)
        .attr('dy', textHeight + shiftT);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-maxs')
        .attr('x', x0)
        .attr('dy', textHeight + shiftT);
      tooltipStats
        .append('tspan')
        .attr('class', 'tooltip-text-max')
        .attr('x', x0)
        .attr('dy', textHeight + shiftT);
    },
  };

  // Expose API globally.
  window.DS = Object.assign({}, window.DS || {}, {
    WhiskerGraph
  });
})(window);
<|endoftext|>


<commit_before>import expect from 'expect'
import React, { Component } from 'react'
import { renderToString } from 'react-dom/server'
import match from '../match'
import RouterContext from '../RoutingContext'
import Link from '../Link'

describe('server rendering', function () {

  class App extends Component {
    render() {
      return (

App

          <Link to="/about" activeClassName="about-is-active">About</Link>{' '}
          <Link to="/dashboard" activeClassName="dashboard-is-active">Dashboard</Link>

            {this.props.children}

      )
    }
  }

  class Dashboard extends Component {
    render() {
      return (

The Dashboard

      )
    }
  }

  class About extends Component {
    render() {
      return (

About

      )
    }
  }

  const DashboardRoute = {
    path: '/dashboard',
    component: Dashboard
  }

  const AboutRoute = {
    path: '/about',
    component: About
  }

  const RedirectRoute = {
    path: '/company',
    onEnter(nextState, replaceState) {
      replaceState(null, '/about')
    }
  }

  const routes = {
    path: '/',
    component: App,
    childRoutes: [ DashboardRoute, AboutRoute, RedirectRoute ]
  }

  it('works', function (done) {
    match({ routes, location: '/dashboard' }, function (error, redirectLocation, renderProps) {
      const string = renderToString(
        <RouterContext {...renderProps} />
      )
      expect(string).toMatch(/The Dashboard/)
      done()
    })
  })

  it('renders active Links as active', function (done) {
    match({ routes, location: '/about' }, function (error, redirectLocation, renderProps) {
      const string = renderToString(
        <RouterContext {...renderProps} />
      )
      expect(string).toMatch(/about-is-active/)
      expect(string).toNotMatch(/dashboard-is-active/)
      done()
    })
  })

  it('sends the redirect location', function (done) {
    match({ routes, location: '/company' }, function (error, redirectLocation) {
      expect(redirectLocation).toExist()
      expect(redirectLocation.pathname).toEqual('/about')
      expect(redirectLocation.search).toEqual('')
      expect(redirectLocation.state).toEqual(null)
      expect(redirectLocation.action).toEqual('REPLACE')
      done()
    })
  })

  it('sends null values when no routes match', function (done) {
    match({ routes, location: '/no-match' }, function (error, redirectLocation, state) {
      expect(error).toNotExist()
      expect(redirectLocation).toNotExist()
      expect(state).toNotExist()
      done()
    })
  })

})
<commit_msg>RoutingContext should be RouterContext in server test<commit_after>import expect from 'expect'
import React, { Component } from 'react'
import { renderToString } from 'react-dom/server'
import match from '../match'
import RouterContext from '../RouterContext'
import Link from '../Link'

describe('server rendering', function () {

  class App extends Component {
    render() {
      return (

App

          <Link to="/about" activeClassName="about-is-active">About</Link>{' '}
          <Link to="/dashboard" activeClassName="dashboard-is-active">Dashboard</Link>

            {this.props.children}

      )
    }
  }

  class Dashboard extends Component {
    render() {
      return (

The Dashboard

      )
    }
  }

  class About extends Component {
    render() {
      return (

About

      )
    }
  }

  const DashboardRoute = {
    path: '/dashboard',
    component: Dashboard
  }

  const AboutRoute = {
    path: '/about',
    component: About
  }

  const RedirectRoute = {
    path: '/company',
    onEnter(nextState, replaceState) {
      replaceState(null, '/about')
    }
  }

  const routes = {
    path: '/',
    component: App,
    childRoutes: [ DashboardRoute, AboutRoute, RedirectRoute ]
  }

  it('works', function (done) {
    match({ routes, location: '/dashboard' }, function (error, redirectLocation, renderProps) {
      const string = renderToString(
        <RouterContext {...renderProps} />
      )
      expect(string).toMatch(/The Dashboard/)
      done()
    })
  })

  it('renders active Links as active', function (done) {
    match({ routes, location: '/about' }, function (error, redirectLocation, renderProps) {
      const string = renderToString(
        <RouterContext {...renderProps} />
      )
      expect(string).toMatch(/about-is-active/)
      expect(string).toNotMatch(/dashboard-is-active/)
      done()
    })
  })

  it('sends the redirect location', function (done) {
    match({ routes, location: '/company' }, function (error, redirectLocation) {
      expect(redirectLocation).toExist()
      expect(redirectLocation.pathname).toEqual('/about')
      expect(redirectLocation.search).toEqual('')
      expect(redirectLocation.state).toEqual(null)
      expect(redirectLocation.action).toEqual('REPLACE')
      done()
    })
  })

  it('sends null values when no routes match', function (done) {
    match({ routes, location: '/no-match' }, function (error, redirectLocation, state) {
      expect(error).toNotExist()
      expect(redirectLocation).toNotExist()
      expect(state).toNotExist()
      done()
    })
  })

})
<|endoftext|>


<commit_before>'use strict';

var ts = require('gulp-typescript');

module.exports = function (gulp, plugins) {
    return function () {
        var tsProject = ts.createProject('tsconfig.json', { typescript: require('typescript') });

        var tsResult = gulp.src([
            'node_modules/@types/core-js/index.d.ts',
            'node_modules/@types/node/index.d.ts',
            'src/assets/**/*.ts'
        ]).pipe(ts(tsProject));

        return tsResult.js
            .pipe(gulp.dest('dist/app'));
    }
};
<commit_msg>Update transpile.js<commit_after>'use strict';

var ts = require('gulp-typescript');

module.exports = function (gulp, plugins) {
    return function () {
        var tsProject = ts.createProject('tsconfig.json', { typescript: require('typescript') });

        var tsResult = gulp.src([
            'node_modules/@types/core-js/index.d.ts',
            'node_modules/@types/node/index.d.ts',
            'src/assets/components/**/*.ts'
        ]).pipe(ts(tsProject));

        return tsResult.js
            .pipe(gulp.dest('dist/app'));
    }
};
<|endoftext|>


<commit_before>/*
 #
 # Copyright (c) 2017 nexB Inc. and others. All rights reserved.
 # https://nexb.com and https://github.com/nexB/scancode-toolkit/
 # The ScanCode software is licensed under the Apache License version 2.0.
 # AboutCode is a trademark of nexB Inc.
 #
 # You may not use this software except in compliance with the License.
 # You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
 # Unless required by applicable law or agreed to in writing, software distributed
 # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 # CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # specific language governing permissions and limitations under the License.
 #
 */

class ComponentDialog {
    constructor(dialogId, aboutCodeDB) {
        this.aboutCodeDB = aboutCodeDB;

        // Define DOM element constants for the modal dialog.
        // TODO: Use nested ids to avoid collisions, e.g. #nodeModal .nodeModalLabel
        this.dialog = $("#componentDialog");
        this.title = this.dialog.find(".modal-title");
        this.status = this.dialog.find("#component-status");
        this.name = this.dialog.find("#component-name");
        this.license = this.dialog.find("#component-license");
        this.owner = this.dialog.find("#component-owner");
        this.copyright = this.dialog.find("#component-copyright");
        this.modified = this.dialog.find('input[name=component-modified]:checked');
        this.deployed = this.dialog.find('input[name=component-deployed]:checked');
        this.codeType = this.dialog.find("#component-code-type");
        this.notes = this.dialog.find("#component-notes");
        this.feature = this.dialog.find("#component-feature");
        this.purpose = this.dialog.find("#component-purpose");
        this.language = this.dialog.find("#component-language");
        this.version = this.dialog.find("#component-version");
        this.homepageUrl = this.dialog.find("#component-homepage-url");
        this.downloadUrl = this.dialog.find("#component-download-url");
        this.licenseUrl = this.dialog.find("#component-license-url");
        this.noticeUrl = this.dialog.find("#component-notice-url");
        this.saveButton = this.dialog.find("button#component-save");
        this.deleteButton = this.dialog.find("button#component-delete");

        // Define the buttons that can be used to close the dialog.
        this.exitButton = this.dialog.find("button#component-exit")
        this.closeButton = this.dialog.find("button#component-close")

        // Make node view modal box draggable
        this.dialog.draggable({ handle: ".modal-header" });
        this.handlers = {};
        this.saveButton.click(() => this._saveComponent());
        this.deleteButton.click(() => this._deleteComponent());

        // Link each close button's click event to a method that checks for unsaved edits.
        this.exitButton.click(() => this._closeComponent());
        this.closeButton.click(() => this._closeComponent());
    }

    database(aboutCodeDB) {
        this.aboutCodeDB = aboutCodeDB;
    }

    // Populate modal input fields with suggestions from ScanCode results
    show(componentId) {
        Promise.all(
            [
                this._component(componentId), this._licenses(componentId),
                this._copyrights(componentId), this._owners(componentId),
                this._language(componentId), this._homepageUrl(componentId)
            ])
            .then(([component, licenses, copyrights, owners, programming_languages, urls]) => {
                this._showDialog(component, {
                    id: componentId,
                    licenses: licenses,
                    copyrights: copyrights,
                    owners: owners,
                    programming_languages: programming_languages,
                    urls: urls
                });
            });
    }

    database(aboutCodeDB) {
        this.aboutCodeDB = aboutCodeDB;
        return this;
    }

    on(event, handler) {
        this.handlers[event] = handler;
        return this;
    }

    _showDialog(component, data) {
        // Add clue data to the select menu options
        let licenses = data.licenses;
        let copyrights = data.copyrights;
        let owners = data.owners;
        let programming_languages = data.programming_languages;
        let urls = data.urls;

        // Add saved data to the select menu options
        licenses = licenses.concat(component.licenses || []);
        copyrights = copyrights.concat(component.copyrights || []);
        owners = owners.concat(component.owner || []);
        programming_languages = $.unique(programming_languages.concat(
            component.programming_language || []));
        urls =  $.unique(urls.concat(
            component.homepage_url || []));

        // update select2 selectors for node view component
        this.license.html('').select2({
            data: $.unique($.map(licenses, (license, i) => {
                return license.key;
            })),
            multiple: true,
            placeholder: "Enter license",
            tags: true
        }, true);

        this.owner.html('').select2({
            data: $.unique(owners),
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter owner",
            tags: true
        }, true);

        this.copyright.html('').select2({
            data: $.unique($.map(copyrights, (copyright, i) => {
                return copyright.statements;
            })),
            multiple: true,
            placeholder: "Enter copyright",
            tags: true
        }, true);

        this.codeType.html('').select2({
            data: component.code_type ? [component.code_type] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter code type",
            tags: true
        }, true);

        this.language.html('').select2({
            data: programming_languages,
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter language",
            tags: true
        }, true);

        this.homepageUrl.html('').select2({
            data: urls,
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter Homepage URL",
            tags: true
        }, true);

        this.downloadUrl.html('').select2({
            data: component.download_url ? [component.download_url] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter Download URL",
            tags: true
        }, true);

        this.licenseUrl.html('').select2({
            data: component.license_url ? [component.license_url] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter License URL",
            tags: true
        }, true);

        this.noticeUrl.html('').select2({
            data: component.notice_url ? [component.notice_url] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter Notice URL",
            tags: true
        }, true);

        this.status.val(component.review_status || "");
        this.name.val(component.name || "");
        this.version.val(component.version || "");
        this.license.val((component.licenses || [])
            .map((license) => license.key));
        this.owner.val(component.owner || []);
        this.copyright.val((component.copyrights || [])
            .map((copyright) => copyright.statements.join("\n")));
        this.codeType.val(component.code_type);
        this.modified.checked = component.is_modified;
        this.deployed.checked = component.is_deployed;
        this.feature.val(component.feature);
        this.purpose.val(component.purpose);
        this.language.val(component.programming_language || []);
        this.homepageUrl.val(component.homepage_url || "");
        this.downloadUrl.val(component.download_url || "");
        this.licenseUrl.val(component.license_url || "");
        this.noticeUrl.val(component.notice_url || "");
        this.notes.val(component.notes || "");

        // Notify only select2 of changes
        $('select').trigger('change.select2');

        this.title.text(data.id);

        // Disable the ability to close the dialog by clicking outside
        // the dialog or pressing the escape key.
        this.dialog.modal({ backdrop: "static", keyboard: false });

        // Retrieve any previously-saved values -- use below in _closeComponent()
        // to compare with any new edits before closing the dialog.
        this.initialSerialization = this.dialog.find("form").serialize();

        this.dialog.modal('show');
    }

    // Check whether the user has made any new edits.
    _closeComponent() {
        // Retrieve the current form values, i.e., including edits not yet saved.
        this.currentSerialization = this.dialog.find("form").serialize();

        if (this.initialSerialization !== this.currentSerialization) {
            return confirm('Your new changes haven\'t been saved.  \n\nAre you sure you want to exit without saving?')
        }
    }

    _saveComponent() {
        let id = this.title.text();
        this._component(id)
            .then(component => {
                // Set the file id on the component.
                return this.aboutCodeDB.File
                    .findOne({
                        attributes: ["id"],
                        where: { path: { $eq: id } }
                    })
                    .then(row => {
                        component.fileId = row.id;
                        return component;
                    });
            })
            .then(component => {
                return {
                    path: id,
                    fileId: component.fileId,
                    review_status: this.status.val(),
                    name: this.name.val(),
                    licenses: $.map(this.license.val() || [], license => {
                        return { key: license };
                    }),
                    copyrights: $.map(this.copyright.val() || [], copyright => {
                        return { statements: copyright.split("\n") };
                    }),
                    code_type: (this.codeType.val() || [null])[0],
                    is_modified: this.deployed.val() == true,
                    is_deployed: this.deployed.val() == true,
                    version: this.version.val(),
                    owner: (this.owner.val() || [null])[0],
                    feature: this.feature.val(),
                    purpose: this.purpose.val(),
                    homepage_url: (this.homepageUrl.val() || [null])[0],
                    download_url: (this.downloadUrl.val() || [null])[0],
                    license_url: (this.licenseUrl.val() || [null])[0],
                    notice_url: (this.noticeUrl.val() || [null])[0],
                    programming_language: (this.language.val() || [null])[0],
                    notes: this.notes.val()
                };
            })
            .then(component => this.aboutCodeDB.setComponent(component))
            .then(component => this.handlers.save(component));
        this.dialog.modal('hide');
    }

    // Delete a created Component inside the Component Modal
    _deleteComponent() {
        let id = this.title.text();
        this.aboutCodeDB.findComponent({ where: { path: id }})
            .then(component => {
                if (component !== null) {
                    return component.destroy()
                        .then(() => this.handlers.delete(component));
                }
            });
    }

    _component(componentId) {
        return this.aboutCodeDB
            .findComponent({where: {path: componentId}})
            .then((component) => component ? component : {});
    }

    _licenses(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB.File
                    .findAll({
                        attributes: [],
                        group: ['licenses.key'],
                        where: { path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.License,
                            attributes: ['key'],
                            where: {key: {$ne: null}}
                        }]
                    });
            })
            .then(rows => $.map(rows, row => row.licenses));
    }

    _copyrights(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: [],
                        group: ['copyrights.statements'],
                        where: {path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.Copyright,
                            attributes: ['statements'],
                            where: {statements: {$ne: null}}
                        }]
                    });
            })
            .then(rows => $.map(rows, row => row.copyrights));
    }

    _owners(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: [],
                        group: ['copyrights.holders'],
                        where: {path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.Copyright,
                            attributes: ['holders'],
                            where: {holders: {$ne: null}}
                        }]
                    });
            })
            .then(rows =>
                $.map(rows, row =>
                    $.map(row.copyrights, copyright => copyright.holders)));
    }

    _language(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: ["programming_language"],
                        group: ['programming_language'],
                        where: {
                            path: {$like: `${componentId}%`},
                            programming_language: {$ne: null}
                        }
                    });
            })
            .then(rows => $.map(rows, row => row.programming_language));
    }

    _homepageUrl(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: [],
                        group: ['urls.url'],
                        where: {path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.Url,
                            attributes: ['url'],
                            where: {url: {$ne: null}}
                        }]
                    });
            })
            .then(rows => $.map(rows, row => $.map(row.urls, url => url.url)));
    }
}

module.exports = ComponentDialog;<commit_msg>Fix Deployed and Modified radio input saving #204<commit_after>/*
 #
 # Copyright (c) 2017 nexB Inc. and others. All rights reserved.
 # https://nexb.com and https://github.com/nexB/scancode-toolkit/
 # The ScanCode software is licensed under the Apache License version 2.0.
 # AboutCode is a trademark of nexB Inc.
 #
 # You may not use this software except in compliance with the License.
 # You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
 # Unless required by applicable law or agreed to in writing, software distributed
 # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 # CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # specific language governing permissions and limitations under the License.
 #
 */

class ComponentDialog {
    constructor(dialogId, aboutCodeDB) {
        this.aboutCodeDB = aboutCodeDB;

        // Define DOM element constants for the modal dialog.
        // TODO: Use nested ids to avoid collisions, e.g. #nodeModal .nodeModalLabel
        this.dialog = $("#componentDialog");
        this.title = this.dialog.find(".modal-title");
        this.status = this.dialog.find("#component-status");
        this.name = this.dialog.find("#component-name");
        this.license = this.dialog.find("#component-license");
        this.owner = this.dialog.find("#component-owner");
        this.copyright = this.dialog.find("#component-copyright");
        this.deployed = this.dialog.find($("input[name=component-deployed]:checked").val());
        this.modified = this.dialog.find($("input[name=component-modified]:checked").val());
        this.codeType = this.dialog.find("#component-code-type");
        this.notes = this.dialog.find("#component-notes");
        this.feature = this.dialog.find("#component-feature");
        this.purpose = this.dialog.find("#component-purpose");
        this.language = this.dialog.find("#component-language");
        this.version = this.dialog.find("#component-version");
        this.homepageUrl = this.dialog.find("#component-homepage-url");
        this.downloadUrl = this.dialog.find("#component-download-url");
        this.licenseUrl = this.dialog.find("#component-license-url");
        this.noticeUrl = this.dialog.find("#component-notice-url");
        this.saveButton = this.dialog.find("button#component-save");
        this.deleteButton = this.dialog.find("button#component-delete");

        // Define the buttons that can be used to close the dialog.
        this.exitButton = this.dialog.find("button#component-exit");
        this.closeButton = this.dialog.find("button#component-close");

        // Make node view modal box draggable
        this.dialog.draggable({ handle: ".modal-header" });
        this.handlers = {};
        this.saveButton.click(() => this._saveComponent());
        this.deleteButton.click(() => this._deleteComponent());

        // Link each close button's click event to a method that checks for unsaved edits.
        this.exitButton.click(() => this._closeComponent());
        this.closeButton.click(() => this._closeComponent());
    }

    database(aboutCodeDB) {
        this.aboutCodeDB = aboutCodeDB;
    }

    // Populate modal input fields with suggestions from ScanCode results
    show(componentId) {
        Promise.all(
            [
                this._component(componentId), this._licenses(componentId),
                this._copyrights(componentId), this._owners(componentId),
                this._language(componentId), this._homepageUrl(componentId)
            ])
            .then(([component, licenses, copyrights, owners, programming_languages, urls]) => {
                this._showDialog(component, {
                    id: componentId,
                    licenses: licenses,
                    copyrights: copyrights,
                    owners: owners,
                    programming_languages: programming_languages,
                    urls: urls
                });
            });
    }

    database(aboutCodeDB) {
        this.aboutCodeDB = aboutCodeDB;
        return this;
    }

    on(event, handler) {
        this.handlers[event] = handler;
        return this;
    }

    _showDialog(component, data) {
        // Add clue data to the select menu options
        let licenses = data.licenses;
        let copyrights = data.copyrights;
        let owners = data.owners;
        let programming_languages = data.programming_languages;
        let urls = data.urls;

        // Add saved data to the select menu options
        licenses = licenses.concat(component.licenses || []);
        copyrights = copyrights.concat(component.copyrights || []);
        owners = owners.concat(component.owner || []);
        programming_languages = $.unique(programming_languages.concat(
            component.programming_language || []));
        urls =  $.unique(urls.concat(
            component.homepage_url || []));

        // update select2 selectors for node view component
        this.license.html('').select2({
            data: $.unique($.map(licenses, (license, i) => {
                return license.key;
            })),
            multiple: true,
            placeholder: "Enter license",
            tags: true
        }, true);

        this.owner.html('').select2({
            data: $.unique(owners),
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter owner",
            tags: true
        }, true);

        this.copyright.html('').select2({
            data: $.unique($.map(copyrights, (copyright, i) => {
                return copyright.statements;
            })),
            multiple: true,
            placeholder: "Enter copyright",
            tags: true
        }, true);

        this.codeType.html('').select2({
            data: component.code_type ? [component.code_type] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter code type",
            tags: true
        }, true);

        this.language.html('').select2({
            data: programming_languages,
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter language",
            tags: true
        }, true);

        this.homepageUrl.html('').select2({
            data: urls,
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter Homepage URL",
            tags: true
        }, true);

        this.downloadUrl.html('').select2({
            data: component.download_url ? [component.download_url] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter Download URL",
            tags: true
        }, true);

        this.licenseUrl.html('').select2({
            data: component.license_url ? [component.license_url] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter License URL",
            tags: true
        }, true);

        this.noticeUrl.html('').select2({
            data: component.notice_url ? [component.notice_url] : [],
            multiple: true,
            maximumSelectionLength: 1,
            placeholder: "Enter Notice URL",
            tags: true
        }, true);

        this.status.val(component.review_status || "");
        this.name.val(component.name || "");
        this.version.val(component.version || "");
        this.license.val((component.licenses || [])
            .map((license) => license.key));
        this.owner.val(component.owner || []);
        this.copyright.val((component.copyrights || [])
            .map((copyright) => copyright.statements.join("\n")));
        this.codeType.val(component.code_type);
        if (component.is_modified !== null && component.is_modified !== undefined) {
            const modifiedValue = component.is_modified ? 'yes' : 'no';
            $(`input[name=component-modified][value='${modifiedValue}']`).prop("checked", true);
        } else {
            $("input[name=component-modified]").prop("checked", false);
        }
        if (component.is_deployed !== null && component.is_deployed !== undefined) {
            const deployedValue = component.is_deployed ? 'yes' : 'no';
            $(`input[name=component-deployed][value='${deployedValue}']`).prop("checked", true);
        } else {
            $("input[name=component-deployed]").prop("checked", false);
        }
        this.feature.val(component.feature);
        this.purpose.val(component.purpose);
        this.language.val(component.programming_language || []);
        this.homepageUrl.val(component.homepage_url || "");
        this.downloadUrl.val(component.download_url || "");
        this.licenseUrl.val(component.license_url || "");
        this.noticeUrl.val(component.notice_url || "");
        this.notes.val(component.notes || "");

        // Notify only select2 of changes
        $('select').trigger('change.select2');

        this.title.text(data.id);

        // Disable the ability to close the dialog by clicking outside
        // the dialog or pressing the escape key.
        this.dialog.modal({ backdrop: "static", keyboard: false });

        // Retrieve any previously-saved values -- use below in _closeComponent()
        // to compare with any new edits before closing the dialog.
        this.initialSerialization = this.dialog.find("form").serialize();

        this.dialog.modal('show');
    }

    // Check whether the user has made any new edits.
    _closeComponent() {
        // Retrieve the current form values, i.e., including edits not yet saved.
        this.currentSerialization = this.dialog.find("form").serialize();

        if (this.initialSerialization !== this.currentSerialization) {
            return confirm('Your new changes haven\'t been saved.  \n\nAre you sure you want to exit without saving?')
        }
    }

    _saveComponent() {
        let id = this.title.text();
        this._component(id)
            .then(component => {
                // Set the file id on the component.
                return this.aboutCodeDB.File
                    .findOne({
                        attributes: ["id"],
                        where: { path: { $eq: id } }
                    })
                    .then(row => {
                        component.fileId = row.id;
                        return component;
                    });
            })
            .then(component => {
                const modifiedValue = $("input[name=component-modified]:checked").val();
                const deployedValue = $("input[name=component-deployed]:checked").val();

                return {
                    path: id,
                    fileId: component.fileId,
                    review_status: this.status.val(),
                    name: this.name.val(),
                    licenses: $.map(this.license.val() || [], license => {
                        return { key: license };
                    }),
                    copyrights: $.map(this.copyright.val() || [], copyright => {
                        return { statements: copyright.split("\n") };
                    }),
                    code_type: (this.codeType.val() || [null])[0],
                    is_modified: modifiedValue ? (modifiedValue === "yes") : null,
                    is_deployed: deployedValue ? (deployedValue === "yes") : null,
                    version: this.version.val(),
                    owner: (this.owner.val() || [null])[0],
                    feature: this.feature.val(),
                    purpose: this.purpose.val(),
                    homepage_url: (this.homepageUrl.val() || [null])[0],
                    download_url: (this.downloadUrl.val() || [null])[0],
                    license_url: (this.licenseUrl.val() || [null])[0],
                    notice_url: (this.noticeUrl.val() || [null])[0],
                    programming_language: (this.language.val() || [null])[0],
                    notes: this.notes.val()
                };
            })
            .then(component => this.aboutCodeDB.setComponent(component))
            .then(component => this.handlers.save(component));
        this.dialog.modal('hide');
    }

    // Delete a created Component inside the Component Modal
    _deleteComponent() {
        let id = this.title.text();
        this.aboutCodeDB.findComponent({ where: { path: id }})
            .then(component => {
                if (component !== null) {
                    return component.destroy()
                        .then(() => this.handlers.delete(component));
                }
            });
    }

    _component(componentId) {
        return this.aboutCodeDB
            .findComponent({where: {path: componentId}})
            .then((component) => component ? component : {});
    }

    _licenses(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB.File
                    .findAll({
                        attributes: [],
                        group: ['licenses.key'],
                        where: { path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.License,
                            attributes: ['key'],
                            where: {key: {$ne: null}}
                        }]
                    });
            })
            .then(rows => $.map(rows, row => row.licenses));
    }

    _copyrights(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: [],
                        group: ['copyrights.statements'],
                        where: {path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.Copyright,
                            attributes: ['statements'],
                            where: {statements: {$ne: null}}
                        }]
                    });
            })
            .then(rows => $.map(rows, row => row.copyrights));
    }

    _owners(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: [],
                        group: ['copyrights.holders'],
                        where: {path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.Copyright,
                            attributes: ['holders'],
                            where: {holders: {$ne: null}}
                        }]
                    });
            })
            .then(rows =>
                $.map(rows, row =>
                    $.map(row.copyrights, copyright => copyright.holders)));
    }

    _language(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: ["programming_language"],
                        group: ['programming_language'],
                        where: {
                            path: {$like: `${componentId}%`},
                            programming_language: {$ne: null}
                        }
                    });
            })
            .then(rows => $.map(rows, row => row.programming_language));
    }

    _homepageUrl(componentId) {
        return this.aboutCodeDB.db
            .then(() => {
                return this.aboutCodeDB
                    .File.findAll({
                        attributes: [],
                        group: ['urls.url'],
                        where: {path: {$like: `${componentId}%`}},
                        include: [{
                            model: this.aboutCodeDB.Url,
                            attributes: ['url'],
                            where: {url: {$ne: null}}
                        }]
                    });
            })
            .then(rows => $.map(rows, row => $.map(row.urls, url => url.url)));
    }
}

module.exports = ComponentDialog;<|endoftext|>


<commit_before>/*jshint loopfunc: true */
(function(){
	'use strict';

	var chai = require('chai');
	var expect = chai.expect;
	var GatewayFacade = require('../../../lib/gateway/GatewayFacade');

	describe('GatewayFacade', function(){

		var gatewayFacade;

		beforeEach(function(){

			gatewayFacade = new GatewayFacade();

			gatewayFacade.config.set('gateway_names', [
				{
					"machine_name": "paypal",
					"pretty_name": "PayPal",
					"module_name": "PaypalGateway"
				},
				{
					"machine_name": "braintree",
					"pretty_name": "Braintree",
					"module_name": "BraintreeGateway"
				}
			]);

			gatewayFacade.refreshGateways();

		});

		describe('Throw exceptions', function(){

			describe('use()', function(){

				it('throw exception when gateway name doesn\'t exists', function(){

					expect(function(){

						gatewayFacade.config.set('gateway_names', {});

						gatewayFacade.refreshGateways();

						gatewayFacade.use('test_gateway');

					}).to.throw(gatewayFacade.GatewayFacadeException);

				});

			});

			describe('resolveGateway() #SPEC', function(){

				var currencies = [ "EUR", "THB", "HKD", "SGD", 	"AUD" ];
				var index;

				for(index = 0; index < currencies.length; index++){

					it('throw exception when currency is ' + currencies[index] + ' and credit card is AMEX', function(){

						expect(function(){

							var order = { 'getCurrency': function(){ return currencies[index]; } };
							var creditCard = { 'getType': function(){ return 'amex'; } };

							gatewayFacade.resolveGateway(order, creditCard);

						}).to.throw(gatewayFacade.GatewayFacadeException);

					});

				}
			});

		});

	GatewayFacade.prototype.resolveGateway = function(order, creditCard){

			if(creditCard.getType() == 'amex'){

				if(order.getCurrency() != 'USD'){

					throw new this.GatewayFacadeException('AMEX is possible to use only for USD.');

				}else{

					return this.use('paypal');

				}

			}else{

				if(['USD','EUR','AUD'].indexOf(order.getCurrency()) > -1){

					return this.use('paypal');

				}else{

					return this.use('braintree');

				}

			}

		};

		describe('Public methods', function(){

			describe('resolveGateway() #SPEC', function(){

				var creditCardTypes = [
					"visa_electron",
					"maestro",
					"dankort",
					"interpayment",
					"unionpay",
					"visa",
					"mastercard",
					"diners_club",
					"discover",
					"jcb"
				];
				var creditCardTypeIndex;

				function testResolveGatewayAsPaypal(currency, gatewayMachineName){

					for(creditCardTypeIndex = 0; creditCardTypeIndex < creditCardTypes.length; creditCardTypeIndex++){

						it('use ' + gatewayMachineName + ' if currency is ' + currency + ' and credit card type is ' + creditCardTypes[creditCardTypeIndex], function(){

							var order = { 'getCurrency': function(){ return currency; } };
					 		var creditCard = { 'getType': function(){ return creditCardTypes[creditCardTypeIndex]; } };

					 		expect(gatewayFacade.resolveGateway(order, creditCard).getMachineName()).to.equal(gatewayMachineName);

						});

					}
				}

				testResolveGatewayAsPaypal('USD', 'paypal');
				testResolveGatewayAsPaypal('EUR', 'paypal');
				testResolveGatewayAsPaypal('AUD', 'paypal');
				testResolveGatewayAsPaypal('THB', 'braintree');
				testResolveGatewayAsPaypal('HKD', 'braintree');
				testResolveGatewayAsPaypal('SGD', 'braintree');

				it('use paypal if currency is USD and credit card type is amex', function(){

					var order = { 'getCurrency': function(){ return 'USD'; } };
					var creditCard = { 'getType': function(){ return 'amex'; } };

					expect(gatewayFacade.resolveGateway(order, creditCard).getMachineName()).to.equal('paypal');

				});

			});

			describe('refreshGateways()', function(){

				it('configured to use only 1 gateway', function(){

					var config = [{
						"machine_name": "paypal",
						"pretty_name": "PayPal",
						"module_name": "PaypalGateway"
					}];

					gatewayFacade.config.set('gateway_names', config);
					gatewayFacade.refreshGateways();

					expect(Object.keys(gatewayFacade.getGateways()).length).to.equal(1);

				});

			});

		});

	});

}());<commit_msg>Update GatewayFacade.test.js<commit_after>/*jshint loopfunc: true */
(function(){
	'use strict';

	var chai = require('chai');
	var expect = chai.expect;
	var GatewayFacade = require('../../../lib/gateway/GatewayFacade');

	describe('GatewayFacade', function(){

		var gatewayFacade;

		beforeEach(function(){

			gatewayFacade = new GatewayFacade();

			gatewayFacade.config.set('gateway_names', [
				{
					"machine_name": "paypal",
					"pretty_name": "PayPal",
					"module_name": "PaypalGateway"
				},
				{
					"machine_name": "braintree",
					"pretty_name": "Braintree",
					"module_name": "BraintreeGateway"
				}
			]);

			gatewayFacade.refreshGateways();

		});

		describe('Throw exceptions', function(){

			describe('use()', function(){

				it('throw exception when gateway name doesn\'t exists', function(){

					expect(function(){

						gatewayFacade.config.set('gateway_names', {});

						gatewayFacade.refreshGateways();

						gatewayFacade.use('test_gateway');

					}).to.throw(gatewayFacade.GatewayFacadeException);

				});

			});

			describe('resolveGateway() #SPEC', function(){

				var currencies = [ "EUR", "THB", "HKD", "SGD", 	"AUD" ];
				var index;

				for(index = 0; index < currencies.length; index++){

					it('throw exception when currency is ' + currencies[index] + ' and credit card is AMEX', function(){

						expect(function(){

							var order = { 'getCurrency': function(){ return currencies[index]; } };
							var creditCard = { 'getType': function(){ return 'amex'; } };

							gatewayFacade.resolveGateway(order, creditCard);

						}).to.throw(gatewayFacade.GatewayFacadeException);

					});

				}
			});

		});

		describe('Public methods', function(){

			describe('resolveGateway() #SPEC', function(){

				var creditCardTypes = [
					"visa_electron",
					"maestro",
					"dankort",
					"interpayment",
					"unionpay",
					"visa",
					"mastercard",
					"diners_club",
					"discover",
					"jcb"
				];
				var creditCardTypeIndex;

				function testResolveGatewayAsPaypal(currency, gatewayMachineName){

					for(creditCardTypeIndex = 0; creditCardTypeIndex < creditCardTypes.length; creditCardTypeIndex++){

						it('use ' + gatewayMachineName + ' if currency is ' + currency + ' and credit card type is ' + creditCardTypes[creditCardTypeIndex], function(){

							var order = { 'getCurrency': function(){ return currency; } };
					 		var creditCard = { 'getType': function(){ return creditCardTypes[creditCardTypeIndex]; } };

					 		expect(gatewayFacade.resolveGateway(order, creditCard).getMachineName()).to.equal(gatewayMachineName);

						});

					}
				}

				testResolveGatewayAsPaypal('USD', 'paypal');
				testResolveGatewayAsPaypal('EUR', 'paypal');
				testResolveGatewayAsPaypal('AUD', 'paypal');
				testResolveGatewayAsPaypal('THB', 'braintree');
				testResolveGatewayAsPaypal('HKD', 'braintree');
				testResolveGatewayAsPaypal('SGD', 'braintree');

				it('use paypal if currency is USD and credit card type is amex', function(){

					var order = { 'getCurrency': function(){ return 'USD'; } };
					var creditCard = { 'getType': function(){ return 'amex'; } };

					expect(gatewayFacade.resolveGateway(order, creditCard).getMachineName()).to.equal('paypal');

				});

			});

			describe('refreshGateways()', function(){

				it('configured to use only 1 gateway', function(){

					var config = [{
						"machine_name": "paypal",
						"pretty_name": "PayPal",
						"module_name": "PaypalGateway"
					}];

					gatewayFacade.config.set('gateway_names', config);
					gatewayFacade.refreshGateways();

					expect(Object.keys(gatewayFacade.getGateways()).length).to.equal(1);

				});

			});

		});

	});

}());
<|endoftext|>


<commit_before>import M_Gizmo from './M_Gizmo';
import Arrow from '../../../low_level/primitives/Arrow';
import ClassicMaterial from '../../../low_level/materials/ClassicMaterial';
import M_Mesh from '../meshes/M_Mesh';

export default class M_DirectionalLightGizmo extends M_Gizmo {
  constructor(glBoostContext, length) {
    super(glBoostContext, null, null);
    this._init(glBoostContext, length);

//    this.isVisible = false;
  }

  _init(glBoostContext, length) {
    this._material = new ClassicMaterial(this._glBoostContext);
    this._mesh = new M_Mesh(glBoostContext,
      new Arrow(this._glBoostContext, length, 3),
      this._material);

    this.addChild(this._mesh);
  }

  set rotate(rotateVec3) {
    this._mesh.rotate = rotateVec3;
  }

  get rotate() {
    return this._mesh.rotate;
  }

  set baseColor(colorVec) {
    this._material.baseColor = colorVec;
  }

  get baseColor() {
    return this._material.baseColor;
  }
}
<commit_msg>Change M_DirectionalLightGizmo Color<commit_after>import M_Gizmo from './M_Gizmo';
import Arrow from '../../../low_level/primitives/Arrow';
import ClassicMaterial from '../../../low_level/materials/ClassicMaterial';
import M_Mesh from '../meshes/M_Mesh';
import Vector4 from '../../../low_level/math/Vector4';

export default class M_DirectionalLightGizmo extends M_Gizmo {
  constructor(glBoostContext, length) {
    super(glBoostContext, null, null);
    this._init(glBoostContext, length);

//    this.isVisible = false;

    this.baseColor = new Vector4(0.8, 0.8, 0, 1);
  }

  _init(glBoostContext, length) {
    this._material = new ClassicMaterial(this._glBoostContext);
    this._mesh = new M_Mesh(glBoostContext,
      new Arrow(this._glBoostContext, length, 3),
      this._material);

    this.addChild(this._mesh);
  }

  set rotate(rotateVec3) {
    this._mesh.rotate = rotateVec3;
  }

  get rotate() {
    return this._mesh.rotate;
  }

  set baseColor(colorVec) {
    this._material.baseColor = colorVec;
  }

  get baseColor() {
    return this._material.baseColor;
  }
}
<|endoftext|>