<commit_before>/*
 * test.lb.base.template.html.js - Unit Tests of lb.base.template.html module
 *
 * Author:    Eric Bréchemier <legalbox@eric.brechemier.name>
 * Copyright: Legal-Box (c) 2010-2011, All Rights Reserved
 * License:   BSD License - http://creativecommons.org/licenses/BSD/
 * Version:   2011-03-29
 *
 * Based on Test Runner from bezen.org JavaScript library
 * CC-BY: Eric Bréchemier - http://bezen.org/javascript/
 */

/*requires lb.base.template.html.js */
/*jslint white:false, onevar:false, plusplus:false */
/*global lb, bezen, window, document */
(function() {
  // Builder of
  // Closure object for Test of lb.base.template.html

  // Define aliases
      /*requires bezen.assert.js */
  var assert = bezen.assert,
      /*requires bezen.object.js */
      object = bezen.object,
      /*requires bezen.testrunner.js */
      testrunner = bezen.testrunner,
      /*requires bezen.dom.js*/
      $ = bezen.$,
      element = bezen.dom.element,
      ELEMENT_NODE = bezen.dom.ELEMENT_NODE,
      ATTRIBUTE_NODE = bezen.dom.ATTRIBUTE_NODE,
      TEXT_NODE = bezen.dom.TEXT_NODE;

  function testNamespace(){

    assert.isTrue( object.exists(window,'lb','base','template','html'),
                            "lb.base.template.html namespace was not found");
  }

  function testTopDownParsing(){
    var ut = lb.base.template.html.topDownParsing;

    var captured = [];
    var catchFilter = function(){
      captured.push(arguments);
    };

    try {
      ut();
      ut(null);
      ut(null,null);
      ut(null,[]);
    } catch (e0) {
     assert.fail("No error expected when required arguments are missing: "+e0);
    }

    try {
      ut({},[]);
    } catch (e1) {
      assert.fail("No error expected when given node is not a node: "+e1);
    }

    try {
      assert.equals(
        ut( document.createElement('div'), [ut,catchFilter] ),
        undefined,
                                  "no processing expected on single element");
      assert.equals(
        ut( document.createAttribute('title'), [ut,catchFilter] ),
        undefined,
                                "no processing expected on single attribute");
      assert.equals(
        ut( document.createTextNode('Text'), [ut,catchFilter] ),
        undefined,
                                "no processing expected on single text node");

      assert.equals(
        ut( document.createComment('Text'), [ut,catchFilter] ),
        undefined,
                             "no processing expected on single comment node");

      assert.equals(
        ut( document.createDocumentFragment(), [ut,catchFilter] ),
        undefined,
                   "no processing expected on single document fragment node");

      // Operations not supported in FF,Chrome,Safari,IE:
      //   * document.createCDATASection('Text')
      //   * document.createProcessingInstruction('target','data')
      // Only supported in Opera.

    } catch(e) {
      assert.fail("top down parsing must not fail on any type of node: "+e);
    }
    assert.arrayEquals( captured, [],
                                   "no recursion expected for single nodes");

    var capturedNames = {};
    function catchAttributes(attribute){
      capturedNames[attribute.name] = true;
    }

    var filters = [ut,catchFilter,catchAttributes];
    var elementWithAttributesOnly = element('div',
      {id:'id value',title:'title value',lang:'lang value'}
    );
    var one = {}, two = 2, three = 'three';
    ut(elementWithAttributesOnly, one, two, three, filters);
    assert.equals( captured.length, 3,
                                    "3 attributes expected to be processed");
    for(var i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],      "params and filters expected in each call (attributes only)");
    }
    assert.objectEquals(capturedNames,{id:true,title:true,lang:true},
                    "attributes id, title and lang expected to be processed");

    var capturedNodeNames = [];
    function captureNodeNames(node){
      capturedNodeNames.push(node.nodeName);
    }

    var deepElement =
      element('h1',{},
        element('h2',{},
          element('h3',{})
        )
      );

    captured = [];
    filters = [ut,catchFilter,captureNodeNames];
    ut(deepElement,one,two,three,filters);
    assert.equals( captured.length, 2,
                                 "2 elements deep expected to be processed");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],   "params and filters expected in each call (elements deep only)");
    }
    assert.arrayEquals(capturedNodeNames, ['H2','H3'],
                          "names of two nodes deep expected to be processed");

    var wideElement =
      element('div',{},
        element('h1'),
        element('h2'),
        element('h3')
      );
    captured = [];
    capturedNodeNames = [];
    ut(wideElement,one,two,three,filters);
    assert.equals( captured.length, 3,
                                 "3 elements wide expected to be processed");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],   "params and filters expected in each call (elements wide only)");
    }
    assert.arrayEquals(capturedNodeNames, ['H1','H2','H3'],
                       "names of three nodes wide expected to be processed");

    var wideAndDeepElement =
      element('div',{},
        element('h1',{},
          element('a'),
          element('b'),
          element('cite')
        ),
        element('h2',{},
          element('dd'),
          element('em'),
          element('form')
        ),
        element('h3',{},
          element('h4'),
          element('h5'),
          element('h6')
        )
      );
    captured = [];
    capturedNodeNames = [];
    ut(wideAndDeepElement,one,two,three,filters);
    assert.equals( captured.length, 12,
                        "12 elements expected to be processed wide and deep");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],
         "params and filters expected in each call (elements wide and deep)");
    }
    assert.arrayEquals(capturedNodeNames,
      ['H1',
         'A','B','CITE',
       'H2',
         'DD','EM','FORM',
       'H3',
         'H4','H5','H6'
      ],
                 "titles of 12 nodes expected to be processed wide and deep");

    var capturedNodeTypes = [];
    function captureNodeTypes(node){
      capturedNodeTypes.push(node.nodeType);
    }
    filters = [ut,catchFilter,captureNodeTypes];

    var mixedElement =
      element('div',{id:'id',title:'title',lang:'lang'},
          'text1',
          element('div'),
          'text2',
          element('div'),
          'text3',
          element('div')
      );
    captured = [];
    ut(mixedElement,one,two,three,filters);
    assert.equals( captured.length, 9,
                "9 nodes expected to be processed in mixed content element");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],       "params and filters expected in each call (mixed content)");
    }
    assert.arrayEquals(capturedNodeTypes,
      [ATTRIBUTE_NODE,ATTRIBUTE_NODE,ATTRIBUTE_NODE,
       TEXT_NODE,ELEMENT_NODE,
       TEXT_NODE,ELEMENT_NODE,
       TEXT_NODE,ELEMENT_NODE],
           "node types of 9 nodes expected to be processed (mixed content)");

    // check that all attributes are processed even if some are removed by a
    // filter
    var parent = null;
    function removeAttributeFromParent(htmlNode){
      if (parent && htmlNode.nodeType === ATTRIBUTE_NODE){
        parent.removeAttributeNode(htmlNode);
      }
    }

    var elementWithAttributes =
      element('div',{id:'British',lang:'en-GB',title:'Sir',dir:'rtl'});

    parent = elementWithAttributes;
    capturedNames = {};
    ut( elementWithAttributes,
        [removeAttributeFromParent, catchAttributes]
    );
    assert.objectEquals(
      capturedNames,
      {id:true,lang:true,title:true,dir:true},
   "all 3 attributes expected to be processed even if attributes are removed");

    // check that all child nodes are processed even if some are removed by a
    // filter
    function removeLastSibling(htmlNode){
      if (htmlNode.parentNode){
        htmlNode.parentNode.removeChild(
          htmlNode.parentNode.lastChild
        );
      }
    }

    var elementWithChildNodes = element('div',{},
      element('h1'),
      element('h2'),
      element('h3'),
      element('h4'),
      element('h5')
    );
    capturedNodeNames = [];
    ut(elementWithChildNodes, [removeLastSibling, captureNodeNames]);
    assert.arrayEquals(capturedNodeNames, ['H1','H2','H3','H4','H5'],
    "all 5 child nodes expected to be processed, even with elements removed");

    // check that all attributes are processed even if a filter fails while
    // processing an attribute
    function failOnAttribute(htmlNode){
      if (htmlNode.nodeType === ATTRIBUTE_NODE){
        throw new Error('Expected error on attribute');
      }
    }

    elementWithAttributes =
      element('div',{id:'British',lang:'en-GB',title:'Sir',dir:'rtl'});
    capturedNames = {};
    ut( elementWithAttributes,
        [failOnAttribute, catchAttributes]
    );
    assert.objectEquals(
      capturedNames,
      {id:true,lang:true,title:true,dir:true},
          "all 3 attributes expected to be processed even if a filter fails");

    // check that all child nodes are processed even if a filter fails while
    // processing a child node
    function failOnElement(htmlNode){
      if (htmlNode.nodeType === ELEMENT_NODE){
        throw new Error('Expected error on element');
      }
    }

    elementWithChildNodes = element('div',{},
      element('h1'),
      element('h2'),
      element('h3'),
      element('h4'),
      element('h5')
    );
    capturedNodeNames = [];
    ut(elementWithChildNodes, [failOnElement, captureNodeNames]);
    assert.arrayEquals(capturedNodeNames, ['H1','H2','H3','H4','H5'],
        "all 5 child nodes expected to be processed, even if a filter fails");
  }

  function testReplaceParams(){
    var ut = lb.base.template.html.replaceParams;

    assert.equals( ut(), null,
                            "null expected when required getter is missing");
    assert.equals( ut(null), null,
                               "null expected when required getter is null");
    assert.equals( ut({}), null,
                     "null expected when required getter is not a function");

    var captured = [];
    var returnValues = [];
    function captureParams(key){
      captured.push(key);
      return returnValues.shift();
    }

    var filter = ut(captureParams);
    assert.equals( typeof filter, 'function',
                              "a filter function is expected to be returned");

    var htmlNode = element('div',{id:'theOne',title:'#param1#'},'#param2#');
    captured = [];
    returnValues = ['value1','value2'];
    filter(htmlNode);
    assert.arrayEquals([
      htmlNode.nodeName,
      htmlNode.getAttribute('id'),
      htmlNode.getAttribute('title'),
      htmlNode.innerHTML
    ],
    [
      'DIV',
      'theOne',
      '#param1#',
      '#param2#'
    ],          "no replacement expected at the element node level for div");
    assert.arrayEquals(captured,[],
             "no call to getter expected at the element node level for div");

    filter( htmlNode.getAttributeNode('title') );
    assert.arrayEquals([
      htmlNode.nodeName,
      htmlNode.getAttribute('id'),
      htmlNode.getAttribute('title'),
      htmlNode.innerHTML
    ],
    [
      'DIV',
      'theOne',
      'value1',
      '#param2#'
    ],                "parameter in title attribute expected to be replaced");
    assert.arrayEquals(captured,['param1'],
                   "call to getter with param1 expected for title attribute");

    filter( htmlNode.firstChild );
    assert.arrayEquals([
      htmlNode.nodeName,
      htmlNode.getAttribute('id'),
      htmlNode.getAttribute('title'),
      htmlNode.innerHTML
    ],
    [
      'DIV',
      'theOne',
      'value1',
      'value2'
    ],                    "parameter in text node expected to be replaced");
    assert.arrayEquals(captured,['param1','param2'],
                "call to getter with param2 expected for text node in div");

    var input = $('testReplaceParams.input');
    assert.isTrue( object.exists(input,'type'),
                        "assert: input element with type attribute expected");
    try {
      filter( input.getAttributeNode('type') );
    } catch(e) {
      assert.fail(
       "Failure in IE setting type of input part of DOM should be avoided: "+e
      );
    }

    var anchor = $('testReplaceParams.anchor');
    captured = [];
    returnValues = ['http://test.example.org'];
    filter( anchor.getAttributeNode('href') );
    assert.arrayEquals([
      anchor.nodeName,
      anchor.getAttribute('href'),
      anchor.innerHTML
    ],
    [
      'A',
      'http://test.example.org',
      'Text'
    ],                      "exact replacement expected for href of anchor");
    assert.arrayEquals(captured,['url'],
                      "call to getter with url expected for href of anchor");

    var image = $('testReplaceParams.image');
    captured = [];
    /* Source: Data URI scheme
     * From Wikipedia, the free encyclopedia
     * http://en.wikipedia.org/wiki/Data_URI_scheme#HTML
     */
    var dataURI = 'data:image/png;base64,'+
    'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP'+
    'C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA'+
    'AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J'+
    'REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq'+
    'ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0'+
    'vr4MkhoXe0rZigAAAABJRU5ErkJggg==';
    returnValues = [dataURI];
    filter( image.getAttributeNode('src') );
    assert.arrayEquals([
      image.nodeName,
      image.getAttribute('src'),
      image.getAttribute('alt')
    ],
    [
      'IMG',
      dataURI,
      'Test Image'
    ],                      "exact replacement expected for image src");
    assert.arrayEquals(captured,['data'],
                      "call to getter with url expected for image src");
  }

  var tests = {
    testNamespace: testNamespace,
    testTopDownParsing: testTopDownParsing,
    testReplaceParams: testReplaceParams
  };

  testrunner.define(tests, "lb.base.template.html");
  return tests;

}());
<commit_msg>Move counter declaration out of for initialization, per JSLint suggestion<commit_after>/*
 * test.lb.base.template.html.js - Unit Tests of lb.base.template.html module
 *
 * Author:    Eric Bréchemier <legalbox@eric.brechemier.name>
 * Copyright: Legal-Box (c) 2010-2011, All Rights Reserved
 * License:   BSD License - http://creativecommons.org/licenses/BSD/
 * Version:   2011-05-06
 *
 * Based on Test Runner from bezen.org JavaScript library
 * CC-BY: Eric Bréchemier - http://bezen.org/javascript/
 */

/*requires lb.base.template.html.js */
/*jslint white:false, onevar:false, plusplus:false */
/*global lb, bezen, window, document */
(function() {
  // Builder of
  // Closure object for Test of lb.base.template.html

  // Define aliases
      /*requires bezen.assert.js */
  var assert = bezen.assert,
      /*requires bezen.object.js */
      object = bezen.object,
      /*requires bezen.testrunner.js */
      testrunner = bezen.testrunner,
      /*requires bezen.dom.js*/
      $ = bezen.$,
      element = bezen.dom.element,
      ELEMENT_NODE = bezen.dom.ELEMENT_NODE,
      ATTRIBUTE_NODE = bezen.dom.ATTRIBUTE_NODE,
      TEXT_NODE = bezen.dom.TEXT_NODE;

  function testNamespace(){

    assert.isTrue( object.exists(window,'lb','base','template','html'),
                            "lb.base.template.html namespace was not found");
  }

  function testTopDownParsing(){
    var ut = lb.base.template.html.topDownParsing;

    var captured = [];
    var catchFilter = function(){
      captured.push(arguments);
    };

    try {
      ut();
      ut(null);
      ut(null,null);
      ut(null,[]);
    } catch (e0) {
     assert.fail("No error expected when required arguments are missing: "+e0);
    }

    try {
      ut({},[]);
    } catch (e1) {
      assert.fail("No error expected when given node is not a node: "+e1);
    }

    try {
      assert.equals(
        ut( document.createElement('div'), [ut,catchFilter] ),
        undefined,
                                  "no processing expected on single element");
      assert.equals(
        ut( document.createAttribute('title'), [ut,catchFilter] ),
        undefined,
                                "no processing expected on single attribute");
      assert.equals(
        ut( document.createTextNode('Text'), [ut,catchFilter] ),
        undefined,
                                "no processing expected on single text node");

      assert.equals(
        ut( document.createComment('Text'), [ut,catchFilter] ),
        undefined,
                             "no processing expected on single comment node");

      assert.equals(
        ut( document.createDocumentFragment(), [ut,catchFilter] ),
        undefined,
                   "no processing expected on single document fragment node");

      // Operations not supported in FF,Chrome,Safari,IE:
      //   * document.createCDATASection('Text')
      //   * document.createProcessingInstruction('target','data')
      // Only supported in Opera.

    } catch(e) {
      assert.fail("top down parsing must not fail on any type of node: "+e);
    }
    assert.arrayEquals( captured, [],
                                   "no recursion expected for single nodes");

    var capturedNames = {};
    function catchAttributes(attribute){
      capturedNames[attribute.name] = true;
    }

    var filters = [ut,catchFilter,catchAttributes];
    var elementWithAttributesOnly = element('div',
      {id:'id value',title:'title value',lang:'lang value'}
    );
    var one = {}, two = 2, three = 'three';
    ut(elementWithAttributesOnly, one, two, three, filters);
    assert.equals( captured.length, 3,
                                    "3 attributes expected to be processed");
    var i;
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],      "params and filters expected in each call (attributes only)");
    }
    assert.objectEquals(capturedNames,{id:true,title:true,lang:true},
                    "attributes id, title and lang expected to be processed");

    var capturedNodeNames = [];
    function captureNodeNames(node){
      capturedNodeNames.push(node.nodeName);
    }

    var deepElement =
      element('h1',{},
        element('h2',{},
          element('h3',{})
        )
      );

    captured = [];
    filters = [ut,catchFilter,captureNodeNames];
    ut(deepElement,one,two,three,filters);
    assert.equals( captured.length, 2,
                                 "2 elements deep expected to be processed");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],   "params and filters expected in each call (elements deep only)");
    }
    assert.arrayEquals(capturedNodeNames, ['H2','H3'],
                          "names of two nodes deep expected to be processed");

    var wideElement =
      element('div',{},
        element('h1'),
        element('h2'),
        element('h3')
      );
    captured = [];
    capturedNodeNames = [];
    ut(wideElement,one,two,three,filters);
    assert.equals( captured.length, 3,
                                 "3 elements wide expected to be processed");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],   "params and filters expected in each call (elements wide only)");
    }
    assert.arrayEquals(capturedNodeNames, ['H1','H2','H3'],
                       "names of three nodes wide expected to be processed");

    var wideAndDeepElement =
      element('div',{},
        element('h1',{},
          element('a'),
          element('b'),
          element('cite')
        ),
        element('h2',{},
          element('dd'),
          element('em'),
          element('form')
        ),
        element('h3',{},
          element('h4'),
          element('h5'),
          element('h6')
        )
      );
    captured = [];
    capturedNodeNames = [];
    ut(wideAndDeepElement,one,two,three,filters);
    assert.equals( captured.length, 12,
                        "12 elements expected to be processed wide and deep");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],
         "params and filters expected in each call (elements wide and deep)");
    }
    assert.arrayEquals(capturedNodeNames,
      ['H1',
         'A','B','CITE',
       'H2',
         'DD','EM','FORM',
       'H3',
         'H4','H5','H6'
      ],
                 "titles of 12 nodes expected to be processed wide and deep");

    var capturedNodeTypes = [];
    function captureNodeTypes(node){
      capturedNodeTypes.push(node.nodeType);
    }
    filters = [ut,catchFilter,captureNodeTypes];

    var mixedElement =
      element('div',{id:'id',title:'title',lang:'lang'},
          'text1',
          element('div'),
          'text2',
          element('div'),
          'text3',
          element('div')
      );
    captured = [];
    ut(mixedElement,one,two,three,filters);
    assert.equals( captured.length, 9,
                "9 nodes expected to be processed in mixed content element");
    for (i=0; i<captured.length; i++){
      assert.arrayEquals(
        [
          captured[i][1],
          captured[i][2],
          captured[i][3],
          captured[i][4]
        ],
        [
          one, two, three, filters
        ],       "params and filters expected in each call (mixed content)");
    }
    assert.arrayEquals(capturedNodeTypes,
      [ATTRIBUTE_NODE,ATTRIBUTE_NODE,ATTRIBUTE_NODE,
       TEXT_NODE,ELEMENT_NODE,
       TEXT_NODE,ELEMENT_NODE,
       TEXT_NODE,ELEMENT_NODE],
           "node types of 9 nodes expected to be processed (mixed content)");

    // check that all attributes are processed even if some are removed by a
    // filter
    var parent = null;
    function removeAttributeFromParent(htmlNode){
      if (parent && htmlNode.nodeType === ATTRIBUTE_NODE){
        parent.removeAttributeNode(htmlNode);
      }
    }

    var elementWithAttributes =
      element('div',{id:'British',lang:'en-GB',title:'Sir',dir:'rtl'});

    parent = elementWithAttributes;
    capturedNames = {};
    ut( elementWithAttributes,
        [removeAttributeFromParent, catchAttributes]
    );
    assert.objectEquals(
      capturedNames,
      {id:true,lang:true,title:true,dir:true},
   "all 3 attributes expected to be processed even if attributes are removed");

    // check that all child nodes are processed even if some are removed by a
    // filter
    function removeLastSibling(htmlNode){
      if (htmlNode.parentNode){
        htmlNode.parentNode.removeChild(
          htmlNode.parentNode.lastChild
        );
      }
    }

    var elementWithChildNodes = element('div',{},
      element('h1'),
      element('h2'),
      element('h3'),
      element('h4'),
      element('h5')
    );
    capturedNodeNames = [];
    ut(elementWithChildNodes, [removeLastSibling, captureNodeNames]);
    assert.arrayEquals(capturedNodeNames, ['H1','H2','H3','H4','H5'],
    "all 5 child nodes expected to be processed, even with elements removed");

    // check that all attributes are processed even if a filter fails while
    // processing an attribute
    function failOnAttribute(htmlNode){
      if (htmlNode.nodeType === ATTRIBUTE_NODE){
        throw new Error('Expected error on attribute');
      }
    }

    elementWithAttributes =
      element('div',{id:'British',lang:'en-GB',title:'Sir',dir:'rtl'});
    capturedNames = {};
    ut( elementWithAttributes,
        [failOnAttribute, catchAttributes]
    );
    assert.objectEquals(
      capturedNames,
      {id:true,lang:true,title:true,dir:true},
          "all 3 attributes expected to be processed even if a filter fails");

    // check that all child nodes are processed even if a filter fails while
    // processing a child node
    function failOnElement(htmlNode){
      if (htmlNode.nodeType === ELEMENT_NODE){
        throw new Error('Expected error on element');
      }
    }

    elementWithChildNodes = element('div',{},
      element('h1'),
      element('h2'),
      element('h3'),
      element('h4'),
      element('h5')
    );
    capturedNodeNames = [];
    ut(elementWithChildNodes, [failOnElement, captureNodeNames]);
    assert.arrayEquals(capturedNodeNames, ['H1','H2','H3','H4','H5'],
        "all 5 child nodes expected to be processed, even if a filter fails");
  }

  function testReplaceParams(){
    var ut = lb.base.template.html.replaceParams;

    assert.equals( ut(), null,
                            "null expected when required getter is missing");
    assert.equals( ut(null), null,
                               "null expected when required getter is null");
    assert.equals( ut({}), null,
                     "null expected when required getter is not a function");

    var captured = [];
    var returnValues = [];
    function captureParams(key){
      captured.push(key);
      return returnValues.shift();
    }

    var filter = ut(captureParams);
    assert.equals( typeof filter, 'function',
                              "a filter function is expected to be returned");

    var htmlNode = element('div',{id:'theOne',title:'#param1#'},'#param2#');
    captured = [];
    returnValues = ['value1','value2'];
    filter(htmlNode);
    assert.arrayEquals([
      htmlNode.nodeName,
      htmlNode.getAttribute('id'),
      htmlNode.getAttribute('title'),
      htmlNode.innerHTML
    ],
    [
      'DIV',
      'theOne',
      '#param1#',
      '#param2#'
    ],          "no replacement expected at the element node level for div");
    assert.arrayEquals(captured,[],
             "no call to getter expected at the element node level for div");

    filter( htmlNode.getAttributeNode('title') );
    assert.arrayEquals([
      htmlNode.nodeName,
      htmlNode.getAttribute('id'),
      htmlNode.getAttribute('title'),
      htmlNode.innerHTML
    ],
    [
      'DIV',
      'theOne',
      'value1',
      '#param2#'
    ],                "parameter in title attribute expected to be replaced");
    assert.arrayEquals(captured,['param1'],
                   "call to getter with param1 expected for title attribute");

    filter( htmlNode.firstChild );
    assert.arrayEquals([
      htmlNode.nodeName,
      htmlNode.getAttribute('id'),
      htmlNode.getAttribute('title'),
      htmlNode.innerHTML
    ],
    [
      'DIV',
      'theOne',
      'value1',
      'value2'
    ],                    "parameter in text node expected to be replaced");
    assert.arrayEquals(captured,['param1','param2'],
                "call to getter with param2 expected for text node in div");

    var input = $('testReplaceParams.input');
    assert.isTrue( object.exists(input,'type'),
                        "assert: input element with type attribute expected");
    try {
      filter( input.getAttributeNode('type') );
    } catch(e) {
      assert.fail(
       "Failure in IE setting type of input part of DOM should be avoided: "+e
      );
    }

    var anchor = $('testReplaceParams.anchor');
    captured = [];
    returnValues = ['http://test.example.org'];
    filter( anchor.getAttributeNode('href') );
    assert.arrayEquals([
      anchor.nodeName,
      anchor.getAttribute('href'),
      anchor.innerHTML
    ],
    [
      'A',
      'http://test.example.org',
      'Text'
    ],                      "exact replacement expected for href of anchor");
    assert.arrayEquals(captured,['url'],
                      "call to getter with url expected for href of anchor");

    var image = $('testReplaceParams.image');
    captured = [];
    /* Source: Data URI scheme
     * From Wikipedia, the free encyclopedia
     * http://en.wikipedia.org/wiki/Data_URI_scheme#HTML
     */
    var dataURI = 'data:image/png;base64,'+
    'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP'+
    'C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA'+
    'AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J'+
    'REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq'+
    'ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0'+
    'vr4MkhoXe0rZigAAAABJRU5ErkJggg==';
    returnValues = [dataURI];
    filter( image.getAttributeNode('src') );
    assert.arrayEquals([
      image.nodeName,
      image.getAttribute('src'),
      image.getAttribute('alt')
    ],
    [
      'IMG',
      dataURI,
      'Test Image'
    ],                      "exact replacement expected for image src");
    assert.arrayEquals(captured,['data'],
                      "call to getter with url expected for image src");
  }

  var tests = {
    testNamespace: testNamespace,
    testTopDownParsing: testTopDownParsing,
    testReplaceParams: testReplaceParams
  };

  testrunner.define(tests, "lb.base.template.html");
  return tests;

}());
<|endoftext|>


<commit_before>'use strict';

var expect = require('chai').expect;

var SessionStore = require('../../index');
var sessionStore = require('../session-store');
var TestManager = require('../test-manager');

describe('SessionStore#createDatabaseTable(cb)', function() {

	before(TestManager.tearDown);

	describe('when the session database table does not yet exist', function() {

		after(TestManager.tearDown);

		it('should create it', function(done) {

			sessionStore.createDatabaseTable(function(error) {

				if (error) {
					return done(new Error(error));
				}

				var sql = 'SELECT `session_id`, `data`, `expires` FROM `sessions`';
				var params = [];

				sessionStore.connection.query(sql, params, function(error, result) {

					if (error) {
						return done(new Error(error));
					}

					done();
				});
			});
		});
	});

	describe('when the session database table does not yet exist', function() {

		before(TestManager.setUp);

		it('should do nothing', function(done) {

			sessionStore.createDatabaseTable(function(error) {

				if (error) {
					return done(new Error(error));
				}

				done();
			});
		});
	});

	describe('when \'options.createDatabaseTable\' is set to FALSE', function() {

		var originalSync;

		before(function() {

			originalSync = SessionStore.prototype.createDatabaseTable;
		});

		afterEach(function() {

			SessionStore.prototype.createDatabaseTable = originalSync;
		});

		it('should not be called when a new sessionStore object is created', function(done) {

			var called = false;

			SessionStore.prototype.createDatabaseTable = function() {

				called = true;

				done(new Error('Sync method should not have been called'));
			};

			var options = require('../config/database');

			options.createDatabaseTable = false;

			new SessionStore(options, function(error) {

				if (called) {
					return;
				}

				if (error) {
					return done(new Error(error));
				}

				done();
			});
		});
	});

	describe('when \'options.createDatabaseTable\' is set to TRUE', function() {

		var options;
		var originalSync;

		before(function() {

			options = require('../config/database');
			options.createDatabaseTable = true;

			originalSync = SessionStore.prototype.createDatabaseTable;
		});

		afterEach(function() {

			SessionStore.prototype.createDatabaseTable = originalSync;
		});

		it('should be called when a new sessionStore object is created', function(done) {

			var called = false;

			SessionStore.prototype.createDatabaseTable = function(cb) {

				called = true;

				cb && cb();
			};

			new SessionStore(options, function(error) {

				if (error) {
					return done(new Error(error));
				}

				if (!called) {
					return done(new Error('Sync method should have been called'));
				}

				done();
			});
		});

		describe('\'options.schema\'', function() {

			var sessionStore;

			before(function(done) {

				sessionStore = new SessionStore(options, done);
			});

			after(function() {

				sessionStore.closeStore();
			});

			it('should create a database table with the correct name and columns', function(done) {

				options.schema = {
					tableName: 'testSessionTable',
					columnNames: {
						session_id: 'testColumnSessionId',
						expires: 'testColumnExpires',
						data: 'testColumnData'
					}
				};

				var sql = 'SHOW COLUMNS FROM ??';
				var params = [options.schema.tableName];

				sessionStore.connection.query(sql, params, function(error, rows) {

					if (error) {
						return done(error);
					}

					expect(rows).to.be.an('array');
					expect(rows).to.have.length(3);
					expect(rows[0].Field).to.equal(options.schema.columnNames.session_id);
					expect(rows[1].Field).to.equal(options.schema.columnNames.expires);
					expect(rows[2].Field).to.equal(options.schema.columnNames.data);
					done();
				});
			});

			it('set() should work', function(done) {

				sessionStore.set('some-session-id', { some: 'data' }, done);
			});

			it('get(session_id, cb) should work', function(done) {

				var session_id = 'some-session-id';

				sessionStore.set(session_id, { some: 'data' }, function(error) {

					if (error) {
						return done(error);
					}

					sessionStore.get(session_id, done);
				});
			});

			it('destroy() should work', function(done) {

				sessionStore.destroy('some-session-id', done);
			});

			it('length() should work', function(done) {

				sessionStore.length(done);
			});

			it('clear() should work', function(done) {

				sessionStore.clear(done);
			});
		});
	});
});
<commit_msg>Fixed tests<commit_after>'use strict';

var expect = require('chai').expect;

var SessionStore = require('../../index');
var sessionStore = require('../session-store');
var TestManager = require('../test-manager');

describe('SessionStore#createDatabaseTable(cb)', function() {

	before(TestManager.tearDown);

	describe('when the session database table does not yet exist', function() {

		after(TestManager.tearDown);

		it('should create it', function(done) {

			sessionStore.createDatabaseTable(function(error) {

				if (error) {
					return done(new Error(error));
				}

				var sql = 'SELECT `session_id`, `data`, `expires` FROM `sessions`';
				var params = [];

				sessionStore.connection.query(sql, params, function(error, result) {

					if (error) {
						return done(new Error(error));
					}

					done();
				});
			});
		});
	});

	describe('when the session database table does not yet exist', function() {

		before(TestManager.setUp);

		it('should do nothing', function(done) {

			sessionStore.createDatabaseTable(function(error) {

				if (error) {
					return done(new Error(error));
				}

				done();
			});
		});
	});

	describe('when \'options.createDatabaseTable\' is set to FALSE', function() {

		var originalSync;

		before(function() {

			originalSync = SessionStore.prototype.createDatabaseTable;
		});

		afterEach(function() {

			SessionStore.prototype.createDatabaseTable = originalSync;
		});

		it('should not be called when a new sessionStore object is created', function(done) {

			var called = false;

			SessionStore.prototype.createDatabaseTable = function() {

				called = true;

				done(new Error('Sync method should not have been called'));
			};

			var options = require('../config/database');

			options.createDatabaseTable = false;

			new SessionStore(options, function(error) {

				if (called) {
					return;
				}

				if (error) {
					return done(new Error(error));
				}

				done();
			});
		});
	});

	describe('when \'options.createDatabaseTable\' is set to TRUE', function() {

		var options;
		var originalSync;

		beforeEach(function() {

			options = require('../config/database');
			options.createDatabaseTable = true;

			originalSync = SessionStore.prototype.createDatabaseTable;
		});

		afterEach(function() {

			SessionStore.prototype.createDatabaseTable = originalSync;
		});

		it('should be called when a new sessionStore object is created', function(done) {

			var called = false;

			SessionStore.prototype.createDatabaseTable = function(cb) {

				called = true;

				cb && cb();
			};

			new SessionStore(options, function(error) {

				if (error) {
					return done(new Error(error));
				}

				if (!called) {
					return done(new Error('Sync method should have been called'));
				}

				done();
			});
		});

		describe('\'options.schema\'', function() {

			var sessionStore;

			beforeEach(function(done) {

				options.schema = {
					tableName: 'testSessionTable',
					columnNames: {
						session_id: 'testColumnSessionId',
						expires: 'testColumnExpires',
						data: 'testColumnData'
					}
				};

				sessionStore = new SessionStore(options, done);
			});

			afterEach(function() {

				sessionStore.closeStore();
			});

			it('should create a database table with the correct name and columns', function(done) {

				var sql = 'SHOW COLUMNS FROM ??';
				var params = [options.schema.tableName];

				sessionStore.connection.query(sql, params, function(error, rows) {

					if (error) {
						return done(error);
					}

					expect(rows).to.be.an('array');
					expect(rows).to.have.length(3);
					expect(rows[0].Field).to.equal(options.schema.columnNames.session_id);
					expect(rows[1].Field).to.equal(options.schema.columnNames.expires);
					expect(rows[2].Field).to.equal(options.schema.columnNames.data);
					done();
				});
			});

			it('set() should work', function(done) {

				sessionStore.set('some-session-id', { some: 'data' }, done);
			});

			it('get(session_id, cb) should work', function(done) {

				var session_id = 'some-session-id';

				sessionStore.set(session_id, { some: 'data' }, function(error) {

					if (error) {
						return done(error);
					}

					sessionStore.get(session_id, done);
				});
			});

			it('destroy() should work', function(done) {

				sessionStore.destroy('some-session-id', done);
			});

			it('length() should work', function(done) {

				sessionStore.length(done);
			});

			it('clear() should work', function(done) {

				sessionStore.clear(done);
			});
		});
	});
});
<|endoftext|>


<commit_before>import { expect } from 'chai';
import gonzales from 'gonzales-pe';

describe('Gonzales', function() {

  var ast;

  describe('SASS', function() {

    it('Should take inequality', function() {
      var str = `$a: 1 != 2;`;

      ast = gonzales.parse(str, {
        syntax: 'sass'
      });
      expect(ast).to.be.an('object');
    });

    it('Should take multiple braces in functions', function() {
      var str = `$a: cell((1.75));`;

      ast = gonzales.parse(str, {
        syntax: 'sass'
      });
      expect(ast).to.be.an('object');
    });

  });

  describe('SCSS', function() {

    it('Should take inequality', function() {
      var str = `$a: 1 != 2;`;

      ast = gonzales.parse(str, {
        syntax: 'scss'
      });
      expect(ast).to.be.an('object');
    });

    it('Should take multiple braces in functions', function() {
      var str = `$a: cell((1.75));`;

      ast = gonzales.parse(str, {
        syntax: 'scss'
      });
      expect(ast).to.be.an('object');
    });
  });

  describe('LESS', function() {

    it('should parse extends', function() {
      var str = `.animal {
  background-color: black;
  color: white;
}
.bear {
  &:extend(.animal);
  background-color: brown;
}`;

      ast = gonzales.parse(str, {
        syntax: 'less'
      });
      expect(ast).to.be.an('object');
    });

  });

  it('should return error message with invalid syntax', function(done) {
    var invalid = '$a = foo', msg;
    try {
      gonzales.parse(invalid, { syntax: 'sass' });
      done(new Error('No error was thrown'));
    } catch (e) {
      msg = e.toString();
      expect(e.line).to.eql(1);
      expect(e.syntax).to.eql('sass');
      expect(msg).to.contain('Parsing error: Please check validity of the block starting from line #1');
      expect(msg).to.contain('1*| ' + invalid);
      done();
    }
  });

});
<commit_msg>Test for !optional in SCSS. Fix #757<commit_after>import { expect } from 'chai';
import gonzales from 'gonzales-pe';

describe('Gonzales', function() {

  var ast;

  describe('SASS', function() {

    it('Should take inequality', function() {
      var str = `$a: 1 != 2;`;

      ast = gonzales.parse(str, {
        syntax: 'sass'
      });
      expect(ast).to.be.an('object');
    });

    it('Should take multiple braces in functions', function() {
      var str = `$a: cell((1.75));`;

      ast = gonzales.parse(str, {
        syntax: 'sass'
      });
      expect(ast).to.be.an('object');
    });

  });

  describe('SCSS', function() {

    it('Should take inequality', function() {
      var str = `$a: 1 != 2;`;

      ast = gonzales.parse(str, {
        syntax: 'scss'
      });
      expect(ast).to.be.an('object');
    });

    it('Should take multiple braces in functions', function() {
      var str = `$a: cell((1.75));`;

      ast = gonzales.parse(str, {
        syntax: 'scss'
      });
      expect(ast).to.be.an('object');
    });

    it('Should take !optional', ()=> {
      var str = `
.foo { color: Red; }

.bar { @extend .foo; }

.foobar { @extend .foo !optional; }
`;

      ast = gonzales.parse(str, {
        syntax: 'scss'
      });
      expect(ast).to.be.an('object');
    });

  });

  describe('LESS', function() {

    it('should parse extends', function() {
      var str = `.animal {
  background-color: black;
  color: white;
}
.bear {
  &:extend(.animal);
  background-color: brown;
}`;

      ast = gonzales.parse(str, {
        syntax: 'less'
      });
      expect(ast).to.be.an('object');
    });

  });

  it('should return error message with invalid syntax', function(done) {
    var invalid = '$a = foo', msg;
    try {
      gonzales.parse(invalid, { syntax: 'sass' });
      done(new Error('No error was thrown'));
    } catch (e) {
      msg = e.toString();
      expect(e.line).to.eql(1);
      expect(e.syntax).to.eql('sass');
      expect(msg).to.contain('Parsing error: Please check validity of the block starting from line #1');
      expect(msg).to.contain('1*| ' + invalid);
      done();
    }
  });

});
<|endoftext|>


<commit_before>import React from 'react';
import {shallow} from 'enzyme';
import path from 'path';

import TabHeaderView from '../../lib/views/tab-header-view';

describe('TabHeaderView', function() {
  function build(options = {}) {
    const props = {
      currentWorkDir: undefined,
      onDidChangeWorkDirs: undefined,
      handleWorkDirSelect: undefined,
      getCurrentWorkDirs: () => [],
      ...options,
    }
    return shallow(<TabHeaderView {...props}/>);
  }

  describe('with a select listener and paths', function() {
    let wrapper, select;
    const path1 = path.normalize('test/path/project1');
    const path2 = path.normalize('2nd-test/path/project2');
    const paths = [path1, path2];

    beforeEach(function() {
      select = sinon.spy();
      wrapper = build({handleWorkDirSelect: select, getCurrentWorkDirs: () => paths, currentWorkDir: path2});
    });

    it('renders an option for all given working directories', function() {
      wrapper.find('option').forEach(function(node, index) {
        assert.strictEqual(node.props().value, paths[index]);
        assert.strictEqual(node.children().text(), path.basename(paths[index]));
      });
    });

    it('selects the current working directory\'s path', function() {
      assert.strictEqual(wrapper.find('select').props().value, path2);
    });

    it('calls handleWorkDirSelect on select', function() {
      wrapper.find('select').simulate('change', {target: {value: path1}});
      assert.isTrue(select.calledWith({target: {value: path1}}));
    });

    it('updates paths', function() {
      const path3 = 'test3/path/project3';
      paths.push(path3);
      wrapper.instance().updateWorkDirs();
      assert.strictEqual(wrapper.find('option').length, 3);
    })
  });

  describe('with onDidChangeWorkDirs', function() {
    let wrapper, changeSpy, disposeSpy;

    beforeEach(function() {
      disposeSpy = sinon.spy();
      const stub = sinon.stub().callsFake(function(updateWorkDirs) {
        updateWorkDirs();
        return {dispose: disposeSpy};
      });
      changeSpy = sinon.spy(stub);
      wrapper = build({onDidChangeWorkDirs: changeSpy});
    });

    it('calls onDidChangeWorkDirs with updateWorkDirs', function() {
      assert.isTrue(changeSpy.calledWith(wrapper.instance().updateWorkDirs));
    });

    it('calls dispose on unmount', function() {
      wrapper.unmount();
      assert.isTrue(disposeSpy.called);
    });

    it('does nothing on unmount without a disposable', function() {
      wrapper.instance().disposable = undefined;
      wrapper.unmount();
      assert.isFalse(disposeSpy.called);
    });

  });

  describe('with no paths', function() {
    let wrapper;

    beforeEach(function() {
      wrapper = build();
    });

    it('renders no options', function() {
      assert.isTrue(wrapper.find('select').children().isEmpty());
    });
  });
});
<commit_msg>lints<commit_after>import React from 'react';
import {shallow} from 'enzyme';
import path from 'path';

import TabHeaderView from '../../lib/views/tab-header-view';

describe('TabHeaderView', function() {
  function build(options = {}) {
    const props = {
      currentWorkDir: undefined,
      onDidChangeWorkDirs: undefined,
      handleWorkDirSelect: undefined,
      getCurrentWorkDirs: () => [],
      ...options,
    };
    return shallow(<TabHeaderView {...props} />);
  }

  describe('with a select listener and paths', function() {
    let wrapper, select;
    const path1 = path.normalize('test/path/project1');
    const path2 = path.normalize('2nd-test/path/project2');
    const paths = [path1, path2];

    beforeEach(function() {
      select = sinon.spy();
      wrapper = build({handleWorkDirSelect: select, getCurrentWorkDirs: () => paths, currentWorkDir: path2});
    });

    it('renders an option for all given working directories', function() {
      wrapper.find('option').forEach(function(node, index) {
        assert.strictEqual(node.props().value, paths[index]);
        assert.strictEqual(node.children().text(), path.basename(paths[index]));
      });
    });

    it('selects the current working directory\'s path', function() {
      assert.strictEqual(wrapper.find('select').props().value, path2);
    });

    it('calls handleWorkDirSelect on select', function() {
      wrapper.find('select').simulate('change', {target: {value: path1}});
      assert.isTrue(select.calledWith({target: {value: path1}}));
    });

    it('updates paths', function() {
      const path3 = 'test3/path/project3';
      paths.push(path3);
      wrapper.instance().updateWorkDirs();
      assert.strictEqual(wrapper.find('option').length, 3);
    });
  });

  describe('with onDidChangeWorkDirs', function() {
    let wrapper, changeSpy, disposeSpy;

    beforeEach(function() {
      disposeSpy = sinon.spy();
      const stub = sinon.stub().callsFake(function(updateWorkDirs) {
        updateWorkDirs();
        return {dispose: disposeSpy};
      });
      changeSpy = sinon.spy(stub);
      wrapper = build({onDidChangeWorkDirs: changeSpy});
    });

    it('calls onDidChangeWorkDirs with updateWorkDirs', function() {
      assert.isTrue(changeSpy.calledWith(wrapper.instance().updateWorkDirs));
    });

    it('calls dispose on unmount', function() {
      wrapper.unmount();
      assert.isTrue(disposeSpy.called);
    });

    it('does nothing on unmount without a disposable', function() {
      wrapper.instance().disposable = undefined;
      wrapper.unmount();
      assert.isFalse(disposeSpy.called);
    });

  });

  describe('with no paths', function() {
    let wrapper;

    beforeEach(function() {
      wrapper = build();
    });

    it('renders no options', function() {
      assert.isTrue(wrapper.find('select').children().isEmpty());
    });
  });
});
<|endoftext|>


<commit_before>(function($) {
    $(function() {
        var map = null,
            markers = [],
            coordinatesInput = $('input[name="coordinates"]'),
            addressComponents = $(
                'input[name="street_address"], input[name="locality"], input[name="region"], input[name="postal_code"], select[name="country_short"]'
            );

        var addressOnChange = function() {
            var address = addressComponents.map(function() {
                return $.trim($(this).val());
            }).get().join(', ');

            var geocoder = new google.maps.Geocoder();
            geocoder.geocode({
                'address': address
            }, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var latlng = results[0].geometry.location;
                    coordinatesInput.val(latlng.lat() + ', ' + latlng.lng()).trigger('change');
                }
            });

        };

        var placeMarker = function() {
            // clear markers.
            for (var i = 0; i < markers.length; i++) {
                markers[i].setMap(null);
            }
            markers = [];

            var latlng = $.map(coordinatesInput.val().split(','), $.trim);
            var position = new google.maps.LatLng(latlng[0], latlng[1]);

            var marker = new google.maps.Marker({
                position: position,
                draggable: true,
                animation: google.maps.Animation.DROP,
                map: map
            });

            markers.push(marker);

            map.setCenter(position);
            map.setZoom(16);

            google.maps.event.addListener(marker, 'dragend', function() {
                var position = marker.getPosition();
                coordinatesInput.val(position.lat() + ', ' + position.lng());
                map.setCenter(position);
            });
        };

        var initialize = function() {
            console.log('GMAP initialize');
            var mapOptions = {
                center: new google.maps.LatLng(40.712784, -74.005941),
                zoom: 11,
                mapTypeControl: false,
            };
            map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
            if (coordinatesInput.val()) {
                placeMarker();
            }
            addressComponents.on('change', addressOnChange);
            coordinatesInput.on('change', placeMarker);

        };

        if (!(typeof window.google === 'object' && window.google.maps)) {
            throw 'Google Maps API is required. Please register the following ' +
            'JavaScript library http://maps.google.com/maps/api/js'
        } else {
            google.maps.event.addDomListener(window, 'load', initialize);
        }

    });
})(django.jQuery);
<commit_msg>Remove console.log()<commit_after>(function($) {
    $(function() {
        var map = null,
            markers = [],
            coordinatesInput = $('input[name="coordinates"]'),
            addressComponents = $(
                'input[name="street_address"], input[name="locality"], input[name="region"], input[name="postal_code"], select[name="country_short"]'
            );

        var addressOnChange = function() {
            var address = addressComponents.map(function() {
                return $.trim($(this).val());
            }).get().join(', ');

            var geocoder = new google.maps.Geocoder();
            geocoder.geocode({
                'address': address
            }, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var latlng = results[0].geometry.location;
                    coordinatesInput.val(latlng.lat() + ', ' + latlng.lng()).trigger('change');
                }
            });

        };

        var placeMarker = function() {
            // clear markers.
            for (var i = 0; i < markers.length; i++) {
                markers[i].setMap(null);
            }
            markers = [];

            var latlng = $.map(coordinatesInput.val().split(','), $.trim);
            var position = new google.maps.LatLng(latlng[0], latlng[1]);

            var marker = new google.maps.Marker({
                position: position,
                draggable: true,
                animation: google.maps.Animation.DROP,
                map: map
            });

            markers.push(marker);

            map.setCenter(position);
            map.setZoom(16);

            google.maps.event.addListener(marker, 'dragend', function() {
                var position = marker.getPosition();
                coordinatesInput.val(position.lat() + ', ' + position.lng());
                map.setCenter(position);
            });
        };

        var initialize = function() {
            var mapOptions = {
                center: new google.maps.LatLng(40.712784, -74.005941),
                zoom: 11,
                mapTypeControl: false,
            };
            map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
            if (coordinatesInput.val()) {
                placeMarker();
            }
            addressComponents.on('change', addressOnChange);
            coordinatesInput.on('change', placeMarker);

        };

        if (!(typeof window.google === 'object' && window.google.maps)) {
            throw 'Google Maps API is required. Please register the following ' +
            'JavaScript library http://maps.google.com/maps/api/js'
        } else {
            google.maps.event.addDomListener(window, 'load', initialize);
        }

    });
})(django.jQuery);
<|endoftext|>


<commit_before>// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// define defaults for purchase common
cur_frm.cscript.tname = "Supplier Quotation Item";
cur_frm.cscript.fname = "quotation_items";
cur_frm.cscript.other_fname = "purchase_tax_details";

// attach required files
wn.require('erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
wn.require('erpnext/buying/doctype/purchase_common/purchase_common.js');

cur_frm.cscript.onload = function(doc, dt, dn) {
	// set missing values in parent doc
	set_missing_values(doc, {
		fiscal_year: sys_defaults.fiscal_year,
		conversion_rate: 1,
		currency: sys_defaults.currency,
		status: "Draft",
		transaction_date: get_today(),
		is_subcontracted: "No"
	});
}

cur_frm.cscript.refresh = function(doc, dt, dn) {
	erpnext.hide_naming_series();
	cur_frm.cscript.dynamic_label(doc, dt, dn);

	cur_frm.cscript.toggle_contact_section(doc);

	cur_frm.clear_custom_buttons();
	if (doc.docstatus === 1) {
		cur_frm.add_custom_button("Make Purchase Order", cur_frm.cscript.make_purchase_order);
	}
}

cur_frm.cscript.toggle_contact_section = function(doc) {
	console.log(doc.supplier);
	doc.supplier ? unhide_field("contact_section") : hide_field("contact_section");
}

cur_frm.cscript.make_purchase_order = function(doc, dt, dn) {

}

cur_frm.cscript.supplier = function(doc, dt, dn) {
	if (doc.supplier) {
		get_server_fields('get_default_supplier_address',
			JSON.stringify({ supplier: doc.supplier }), '', doc, dt, dn, 1,
			function() { cur_frm.refresh(); });
		cur_frm.cscript.toggle_contact_section(doc);
	}
}

cur_frm.fields_dict['quotation_items'].grid.get_field('project_name').get_query =
	function(doc, cdt, cdn) {
		return "select `tabProject`.name from `tabProject` \
			where `tabProject`.status = \"Open\" and `tabProject`.name like \"%s\" \
			order by `tabProject`.name ASC LIMIT 50";
	}

cur_frm.fields_dict['indent_no'].get_query = function(doc) {
	return "select distinct `tabPurchase Request`.`name` from `tabPurchase Request` \
		where `tabPurchase Request`.company = \"" + doc.company +
		"\" and `tabPurchase Request`.`docstatus` = 1 and \
		`tabPurchase Request`.`status` != \"Stopped\" and \
		ifnull(`tabPurchase Request`.`per_ordered`,0) < 100 and \
		`tabPurchase Request`.%(key)s LIKE \"%s\" \
		order by `tabPurchase Request`.`name` desc limit 50";
}

cur_frm.cscript.supplier_address = function(doc, dt, dn) {
	if (doc.supplier) {
		get_server_fields("get_supplier_address", JSON.stringify({supplier: doc.supplier,
			address: doc.supplier_address, contact: doc.contact_person}), '', doc, dt, dn, 1);
	}
}
cur_frm.cscript.contact_person = cur_frm.cscript.supplier_address;

cur_frm.fields_dict['supplier_address'].get_query = function(doc, cdt, cdn) {
	return "SELECT name, address_line1, city FROM tabAddress WHERE supplier = \"" + doc.supplier
		+ "\" AND docstatus != 2 AND name LIKE \"%s\" ORDER BY name ASC LIMIT 50";
}

cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
	return "SELECT name, CONCAT(first_name, \" \", ifnull(last_name,\"\")) As FullName, \
		department, designation FROM tabContact WHERE supplier = \"" + doc.supplier
		+"\" AND docstatus != 2 AND name LIKE \"%s\" ORDER BY name ASC LIMIT 50";
}

cur_frm.fields_dict.supplier_address.on_new = function(dn) {
	locals['Address'][dn].supplier = locals[cur_frm.doctype][cur_frm.docname].supplier;
	locals['Address'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name;
}

cur_frm.fields_dict.contact_person.on_new = function(dn) {
	locals['Contact'][dn].supplier = locals[cur_frm.doctype][cur_frm.docname].supplier;
	locals['Contact'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name;
}<commit_msg>added button to make Purchase Order from Supplier Quotation<commit_after>// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// define defaults for purchase common
cur_frm.cscript.tname = "Supplier Quotation Item";
cur_frm.cscript.fname = "quotation_items";
cur_frm.cscript.other_fname = "purchase_tax_details";

// attach required files
wn.require('erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
wn.require('erpnext/buying/doctype/purchase_common/purchase_common.js');

cur_frm.cscript.onload = function(doc, dt, dn) {
	// set missing values in parent doc
	set_missing_values(doc, {
		fiscal_year: sys_defaults.fiscal_year,
		conversion_rate: 1,
		currency: sys_defaults.currency,
		status: "Draft",
		transaction_date: get_today(),
		is_subcontracted: "No"
	});
}

cur_frm.cscript.refresh = function(doc, dt, dn) {
	erpnext.hide_naming_series();
	cur_frm.cscript.dynamic_label(doc, dt, dn);

	cur_frm.cscript.toggle_contact_section(doc);

	cur_frm.clear_custom_buttons();
	if (doc.docstatus === 1) {
		cur_frm.add_custom_button("Make Purchase Order", cur_frm.cscript.make_purchase_order);
	}
}

cur_frm.cscript.make_purchase_order = function() {
	var new_po_name = createLocal("Purchase Order");
	$c("dt_map", {
		"docs": compress_doclist([locals['Purchase Order'][new_po_name]]),
		"from_doctype": cur_frm.doc.doctype,
		"to_doctype": "Purchase Order",
		"from_docname": cur_frm.doc.name,
		"from_to_list": JSON.stringify([['Supplier Quotation', 'Purchase Order'],
			['Supplier Quotation Item', 'Purchase Order Item'],
			['Purchase Taxes and Charges', 'Purchase Taxes and Charges']]),
	}, function(r, rt) { loaddoc("Purchase Order", new_po_name) });
}

cur_frm.cscript.supplier = function(doc, dt, dn) {
	if (doc.supplier) {
		get_server_fields('get_default_supplier_address',
			JSON.stringify({ supplier: doc.supplier }), '', doc, dt, dn, 1,
			function() { cur_frm.refresh(); });
		cur_frm.cscript.toggle_contact_section(doc);
	}
}

cur_frm.cscript.uom = function(doc, cdt, cdn) {
	// no need to trigger updation of stock uom, as this field doesn't exist in supplier quotation
}

cur_frm.fields_dict['quotation_items'].grid.get_field('project_name').get_query =
	function(doc, cdt, cdn) {
		return "select `tabProject`.name from `tabProject` \
			where `tabProject`.status = \"Open\" and `tabProject`.name like \"%s\" \
			order by `tabProject`.name ASC LIMIT 50";
	}

cur_frm.fields_dict['indent_no'].get_query = function(doc) {
	return "select distinct `tabPurchase Request`.`name` from `tabPurchase Request` \
		where `tabPurchase Request`.company = \"" + doc.company +
		"\" and `tabPurchase Request`.`docstatus` = 1 and \
		`tabPurchase Request`.`status` != \"Stopped\" and \
		ifnull(`tabPurchase Request`.`per_ordered`,0) < 100 and \
		`tabPurchase Request`.%(key)s LIKE \"%s\" \
		order by `tabPurchase Request`.`name` desc limit 50";
}

cur_frm.cscript.supplier_address = function(doc, dt, dn) {
	if (doc.supplier) {
		get_server_fields("get_supplier_address", JSON.stringify({supplier: doc.supplier,
			address: doc.supplier_address, contact: doc.contact_person}), '', doc, dt, dn, 1);
	}
}
cur_frm.cscript.contact_person = cur_frm.cscript.supplier_address;

cur_frm.fields_dict['supplier_address'].get_query = function(doc, cdt, cdn) {
	return "SELECT name, address_line1, city FROM tabAddress WHERE supplier = \"" + doc.supplier
		+ "\" AND docstatus != 2 AND name LIKE \"%s\" ORDER BY name ASC LIMIT 50";
}

cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
	return "SELECT name, CONCAT(first_name, \" \", ifnull(last_name,\"\")) As FullName, \
		department, designation FROM tabContact WHERE supplier = \"" + doc.supplier
		+"\" AND docstatus != 2 AND name LIKE \"%s\" ORDER BY name ASC LIMIT 50";
}

cur_frm.fields_dict.supplier_address.on_new = function(dn) {
	locals['Address'][dn].supplier = locals[cur_frm.doctype][cur_frm.docname].supplier;
	locals['Address'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name;
}

cur_frm.fields_dict.contact_person.on_new = function(dn) {
	locals['Contact'][dn].supplier = locals[cur_frm.doctype][cur_frm.docname].supplier;
	locals['Contact'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name;
}<|endoftext|>


<commit_before>/* Initial sidebar toc toggle button*/
$(document).ready(function () {
    var allEntry = $("div.sphinxsidebarwrapper li");
    allEntry.each(function () {
        $(this).prepend("");
        var childUL = $(this).find("ul");
        if(childUL.length && childUL.first().children().length) {
            $(this).addClass("closed");
            $(this).find("ul").first().hide();
        }
        else
            $(this).addClass("leaf");
    });
    $('body').show();
});

/*Sidebar toc toggle button behavior*/
function toggle(elem) {
    if($(elem).parent().hasClass("closed")) {
        $(elem).parent().find("ul").first().show();
        $(elem).parent().removeClass("closed").addClass("opened");
    }
    else if($(elem).parent().hasClass("opened")) {
        $(elem).parent().find("ul").first().hide();
        $(elem).parent().removeClass("opened").addClass("closed");
    }
}<commit_msg>Improve sidebar (#3898)<commit_after>/* Initial sidebar toc toggle button*/
$(document).ready(function () {
    var allEntry = $("div.sphinxsidebarwrapper li");
    var subEntry = $("div.sphinxsidebarwrapper").children("ul").first().children("li");
    if(subEntry.length == 1) allEntry = subEntry.find("li");
    allEntry.each(function () {
        $(this).prepend("");
        var childUL = $(this).find("ul");
        if(childUL.length && childUL.first().children().length) {
            $(this).addClass("closed");
            $(this).find("ul").first().hide();
        }
        else
            $(this).addClass("leaf");
    });
    $('body').show();
});

/*Sidebar toc toggle button behavior*/
function toggle(elem) {
    if($(elem).parent().hasClass("closed")) {
        $(elem).parent().find("ul").first().show();
        $(elem).parent().removeClass("closed").addClass("opened");
    }
    else if($(elem).parent().hasClass("opened")) {
        $(elem).parent().find("ul").first().hide();
        $(elem).parent().removeClass("opened").addClass("closed");
    }
}<|endoftext|>


<commit_before>define(
[
    'models',
    'views/common',
    'views/dialogs',
    'text!templates/cluster/network_tab.html',
    'text!templates/cluster/network_tab_view.html',
    'text!templates/cluster/verify_network_control.html'
],
function(models, commonViews, dialogViews, networkTabTemplate, networkTabViewModeTemplate, networkTabVerificationControlTemplate) {
    'use strict';
    var NetworkTab, NetworkTabVerificationControl;

    NetworkTab = commonViews.Tab.extend({
        template: _.template(networkTabTemplate),
        viewModeTemplate: _.template(networkTabViewModeTemplate),
        updateInterval: 3000,
        events: {
            'keyup .row input': 'makeChanges',
            'change .row select': 'makeChanges',
            'click .apply-btn:not([disabled])': 'apply',
            'click .verify-networks-btn:not([disabled])': 'verifyNetworks',
            'click .nav a:not(.active)': 'changeMode',
            'click .net-manager input:not([checked])': 'changeManager',
            'keyup .range': 'displayRange'
        },
        makeChanges: function(e) {
            if (e) {
                this.$(e.target).parents('.control-group').removeClass('error').find('.help-inline').text('');
                var attribute = $.trim(this.$(e.target).parent().attr('class'));
                var network = this.$(e.target).parents('.control-group').data('network-id');
                var newValue = this.$(e.target).val();
                if (attribute != 'cidr') {
                    newValue = parseInt(newValue, 10);
                }
                this.networks.get(network).on('error', function(model, errors) {
                    this.$(e.target).parents('.control-group').find('.error .help-inline').text(errors.cidr || errors.vlan_start || errors.amount);
                    this.$(e.target).parents('.control-group').addClass('error');
                }, this);
                this.networks.get(network).set(attribute, newValue);
            } else {
                this.$('.control-group').removeClass('error').find('.help-inline').text('');
            }
            if (_.isEqual(this.networks.toJSON(), this.settingsSaved) && this.model.get('net_manager') == this.$('.net-manager input[checked]').val()) {
                this.$('.apply-btn').attr('disabled', true);
            } else {
                this.$('.apply-btn').attr('disabled', false);
            }
            this.networks.hasChanges = true;
            app.page.removeVerificationTask();
        },
        calculateVlanEnd: function() {
            if (this.$('.net-manager input[checked]').val() == 'VlanManager') {
                var amount = parseInt(this.$('.fixed-row .amount input').val(), 10);
                var vlanStart = parseInt(this.$('.fixed-row .vlan_start input:first').val(), 10);
                var vlanEnd =  vlanStart + amount - 1;
                if (vlanEnd > 4094) {
                    vlanEnd = 4094;
                }
                this.$('input.vlan-end').val(vlanEnd);
            }
        },
        displayRange: function() {
            if (this.$('.net-manager input[checked]').val() == 'VlanManager' && parseInt(this.$('.fixed-row .amount input').val(), 10) > 1 && parseInt(this.$('.fixed-row .vlan_start input:first').val(), 10)) {
                this.$('.fixed-header .vlan').text('VLAN ID range');
                this.$('.fixed-row .vlan_start input:first').addClass('range');
                this.calculateVlanEnd();
                this.$('.vlan-end').show();
            } else {
                this.$('.fixed-header .vlan').text('VLAN ID');
                this.$('.vlan-end').hide();
            }
        },
        changeManager: function(e) {
            this.$('.net-manager input').attr('checked', false);
            this.$(e.target).attr('checked', true);
            this.makeChanges();
            this.$('.fixed-row .amount, .fixed-header .amount, .fixed-row .network_size, .fixed-header .size').toggle().removeClass('hide');
            this.displayRange();
        },
        setValues: function() {
            var valid = true;
            this.$('.control-group').removeClass('error').find('.help-inline').text('');
            this.networks.each(function(network) {
                var row = this.$('.control-group[data-network-name=' + network.get('name') + ']');
                network.on('error', function(model, errors) {
                    valid = false;
                }, this);
                network.set({
                    cidr: $('.cidr input', row).val(),
                    vlan_start: parseInt($('.vlan_start input:first', row).val(), 10),
                    amount: this.$('.net-manager input[checked]').val() == 'FlatDHCPManager' ? 1 : parseInt($('.amount input', row).val(), 10),
                    network_size: parseInt($('.network_size select', row).val(), 10)
                });
            }, this);
            return valid;
        },
        changeMode: function(e) {
            e.preventDefault();
        },
        apply: function() {
            if (this.setValues()) {
                this.$('.apply-btn').attr('disabled', true);
                this.model.update({net_manager: this.$('.net-manager input[checked]').val()});
                Backbone.sync('update', this.networks, {
                    url: '/api/clusters/' + this.model.id + '/save/networks',
                    error: _.bind(function() {
                        this.$('.apply-btn').attr('disabled', false);
                        var dialog = new dialogViews.SimpleMessage({error: true, title: 'Networks'});
                        this.registerSubView(dialog);
                        dialog.render();
                    }, this),
                    success: _.bind(function(task) {
                        if (task && task.status == 'error') {
                            this.$('.apply-btn').attr('disabled', false);
                        } else {
                            this.networks.hasChanges = false;
                            this.settingsSaved = this.networks.toJSON();
                        }
                    }, this),
                    complete: _.bind(function() {
                        this.model.get('tasks').fetch({data: {cluster_id: this.model.id}});
                    }, this)
                });
            }
        },
        scheduleUpdate: function() {
            if (this.model.task('verify_networks', 'running')) {
                this.timeout = _.delay(_.bind(this.update, this), this.updateInterval);
            }
        },
        update: function(force) {
            var task = this.model.task('verify_networks', 'running');
            if (task && (force || app.page.$el.find(this.el).length)) {
                task.fetch({complete: _.bind(this.scheduleUpdate, this)});
            }
        },
        startVerification: function() {
            var task = new models.Task();
            task.save({}, {
                type: 'PUT',
                url: '/api/clusters/' + this.model.id + '/verify/networks',
                data: JSON.stringify(this.networks),
                error:  _.bind(function() {
                        this.$('.verify-networks-btn').attr('disabled', false);
                        var dialog = new dialogViews.SimpleMessage({error: true, title: 'Network verification'});
                        this.registerSubView(dialog);
                        dialog.render();
                    }, this),
                complete: _.bind(function() {
                    this.model.get('tasks').fetch({data: {cluster_id: this.model.id}});
                }, this)
            });
        },
        verifyNetworks: function() {
            if (this.setValues()) {
                this.$('.verify-networks-btn').attr('disabled', true);
                app.page.removeVerificationTask().done(_.bind(this.startVerification, this));
            }
        },
        beforeTearDown: function() {
            if (this.timeout) {
                clearTimeout(this.timeout);
            }
        },
        bindEvents: function() {
            this.model.get('tasks').bind('remove', this.renderVerificationControl, this);
            this.model.get('tasks').bind('reset', function(){
                this.render();
                this.update(true);
            }, this);
            this.model.get('tasks').bind('change:status', function(task) {
                if ((task.get('name') == 'deploy' || task.get('name') == 'verify_networks') && task.get('status') != 'running') {
                    this.render();
                }
            }, this);
        },
        initialize: function(options) {
            _.defaults(this, options);
            this.model.bind('change:tasks', this.bindEvents, this);
            this.bindEvents();
            if (!this.model.get('networks')) {
                this.networks = new models.Networks();
                this.networks.deferred = this.networks.fetch({data: {cluster_id: this.model.id}});
                this.networks.deferred.done(_.bind(this.render, this));
                this.model.set({'networks': this.networks}, {silent: true});
            } else {
                this.networks = this.model.get('networks');
            }
        },
        renderVerificationControl: function() {
            var verificationView = new NetworkTabVerificationControl({model: this.model, networks: this.networks});
            this.registerSubView(verificationView);
            this.$('.verification-control').html(verificationView.render().el);
        },
        render: function() {
            this.settingsSaved = this.networks.toJSON();
            this.$el.html(this.template({cluster: this.model, networks: this.networks}));
            this.renderVerificationControl();
            return this;
        }
    });

    NetworkTabVerificationControl = Backbone.View.extend({
        template: _.template(networkTabVerificationControlTemplate),
        initialize: function(options) {
            _.defaults(this, options);
        },
        render: function() {
            this.$el.html(this.template({cluster: this.model, networks: this.networks}));
            return this;
        }
    });

    return NetworkTab;
});
<commit_msg>Fixes for networks validation<commit_after>define(
[
    'models',
    'views/common',
    'views/dialogs',
    'text!templates/cluster/network_tab.html',
    'text!templates/cluster/network_tab_view.html',
    'text!templates/cluster/verify_network_control.html'
],
function(models, commonViews, dialogViews, networkTabTemplate, networkTabViewModeTemplate, networkTabVerificationControlTemplate) {
    'use strict';
    var NetworkTab, NetworkTabVerificationControl;

    NetworkTab = commonViews.Tab.extend({
        template: _.template(networkTabTemplate),
        viewModeTemplate: _.template(networkTabViewModeTemplate),
        updateInterval: 3000,
        events: {
            'keyup .row input': 'makeChanges',
            'change .row select': 'makeChanges',
            'click .apply-btn:not([disabled])': 'apply',
            'click .verify-networks-btn:not([disabled])': 'verifyNetworks',
            'click .nav a:not(.active)': 'changeMode',
            'click .net-manager input:not([checked])': 'changeManager',
            'keyup .range': 'displayRange'
        },
        makeChanges: function(e) {
            var row;
            if (e) {
                row = this.$(e.target).parents('.control-group');
            } else {
                row = this.$('.control-group[data-network-name=fixed]');
            }
            row.removeClass('error').find('.help-inline').text('');
            this.networks.get(row.data('network-id')).on('error', function(model, errors) {
                row.addClass('error').find('.help-inline').text(errors.cidr || errors.vlan_start || errors.amount);
            }, this);
            this.networks.get(row.data('network-id')).set({
                cidr: $('.cidr input', row).val(),
                vlan_start: parseInt($('.vlan_start input:first', row).val(), 10),
                amount: this.$('.net-manager input[checked]').val() == 'FlatDHCPManager' ? 1 : parseInt($('.amount input', row).val(), 10),
                network_size: parseInt($('.network_size select', row).val(), 10)
            });
            if (_.isEqual(this.networks.toJSON(), this.settingsSaved) && this.model.get('net_manager') == this.$('.net-manager input[checked]').val()) {
                this.$('.apply-btn').attr('disabled', true);
            } else {
                this.$('.apply-btn').attr('disabled', false);
            }
            this.networks.hasChanges = true;
            app.page.removeVerificationTask();
        },
        calculateVlanEnd: function() {
            if (this.$('.net-manager input[checked]').val() == 'VlanManager') {
                var amount = parseInt(this.$('.fixed-row .amount input').val(), 10);
                var vlanStart = parseInt(this.$('.fixed-row .vlan_start input:first').val(), 10);
                var vlanEnd =  vlanStart + amount - 1;
                if (vlanEnd > 4094) {
                    vlanEnd = 4094;
                }
                this.$('input.vlan-end').val(vlanEnd);
            }
        },
        displayRange: function() {
            if (this.$('.net-manager input[checked]').val() == 'VlanManager' && parseInt(this.$('.fixed-row .amount input').val(), 10) > 1 && parseInt(this.$('.fixed-row .vlan_start input:first').val(), 10)) {
                this.$('.fixed-header .vlan').text('VLAN ID range');
                this.$('.fixed-row .vlan_start input:first').addClass('range');
                this.calculateVlanEnd();
                this.$('.vlan-end').show();
            } else {
                this.$('.fixed-header .vlan').text('VLAN ID');
                this.$('.vlan-end').hide();
            }
        },
        changeManager: function(e) {
            this.$('.net-manager input').attr('checked', false);
            this.$(e.target).attr('checked', true);
            this.makeChanges();
            this.$('.fixed-row .amount, .fixed-header .amount, .fixed-row .network_size, .fixed-header .size').toggle().removeClass('hide');
            this.displayRange();
        },
        setValues: function() {
            var valid = true;
            this.$('.control-group').removeClass('error').find('.help-inline').text('');
            this.networks.each(function(network) {
                var row = this.$('.control-group[data-network-name=' + network.get('name') + ']');
                network.on('error', function(model, errors) {
                    valid = false;
                }, this);
                network.set({
                    cidr: $('.cidr input', row).val(),
                    vlan_start: parseInt($('.vlan_start input:first', row).val(), 10),
                    amount: this.$('.net-manager input[checked]').val() == 'FlatDHCPManager' ? 1 : parseInt($('.amount input', row).val(), 10),
                    network_size: parseInt($('.network_size select', row).val(), 10)
                });
            }, this);
            return valid;
        },
        changeMode: function(e) {
            e.preventDefault();
        },
        apply: function() {
            if (this.setValues()) {
                this.$('.apply-btn').attr('disabled', true);
                this.model.update({net_manager: this.$('.net-manager input[checked]').val()});
                Backbone.sync('update', this.networks, {
                    url: '/api/clusters/' + this.model.id + '/save/networks',
                    error: _.bind(function() {
                        this.$('.apply-btn').attr('disabled', false);
                        var dialog = new dialogViews.SimpleMessage({error: true, title: 'Networks'});
                        this.registerSubView(dialog);
                        dialog.render();
                    }, this),
                    success: _.bind(function(task) {
                        if (task && task.status == 'error') {
                            this.$('.apply-btn').attr('disabled', false);
                        } else {
                            this.networks.hasChanges = false;
                            this.settingsSaved = this.networks.toJSON();
                        }
                    }, this),
                    complete: _.bind(function() {
                        this.model.get('tasks').fetch({data: {cluster_id: this.model.id}});
                    }, this)
                });
            }
        },
        scheduleUpdate: function() {
            if (this.model.task('verify_networks', 'running')) {
                this.timeout = _.delay(_.bind(this.update, this), this.updateInterval);
            }
        },
        update: function(force) {
            var task = this.model.task('verify_networks', 'running');
            if (task && (force || app.page.$el.find(this.el).length)) {
                task.fetch({complete: _.bind(this.scheduleUpdate, this)});
            }
        },
        startVerification: function() {
            var task = new models.Task();
            task.save({}, {
                type: 'PUT',
                url: '/api/clusters/' + this.model.id + '/verify/networks',
                data: JSON.stringify(this.networks),
                error:  _.bind(function() {
                        this.$('.verify-networks-btn').attr('disabled', false);
                        var dialog = new dialogViews.SimpleMessage({error: true, title: 'Network verification'});
                        this.registerSubView(dialog);
                        dialog.render();
                    }, this),
                complete: _.bind(function() {
                    this.model.get('tasks').fetch({data: {cluster_id: this.model.id}});
                }, this)
            });
        },
        verifyNetworks: function() {
            if (this.setValues()) {
                this.$('.verify-networks-btn').attr('disabled', true);
                app.page.removeVerificationTask().done(_.bind(this.startVerification, this));
            }
        },
        beforeTearDown: function() {
            if (this.timeout) {
                clearTimeout(this.timeout);
            }
        },
        bindEvents: function() {
            this.model.get('tasks').bind('remove', this.renderVerificationControl, this);
            this.model.get('tasks').bind('reset', function(){
                this.render();
                this.update(true);
            }, this);
            this.model.get('tasks').bind('change:status', function(task) {
                if ((task.get('name') == 'deploy' || task.get('name') == 'verify_networks') && task.get('status') != 'running') {
                    this.render();
                }
            }, this);
        },
        initialize: function(options) {
            _.defaults(this, options);
            this.model.bind('change:tasks', this.bindEvents, this);
            this.bindEvents();
            if (!this.model.get('networks')) {
                this.networks = new models.Networks();
                this.networks.deferred = this.networks.fetch({data: {cluster_id: this.model.id}});
                this.networks.deferred.done(_.bind(this.render, this));
                this.model.set({'networks': this.networks}, {silent: true});
            } else {
                this.networks = this.model.get('networks');
            }
        },
        renderVerificationControl: function() {
            var verificationView = new NetworkTabVerificationControl({model: this.model, networks: this.networks});
            this.registerSubView(verificationView);
            this.$('.verification-control').html(verificationView.render().el);
        },
        render: function() {
            this.settingsSaved = this.networks.toJSON();
            this.$el.html(this.template({cluster: this.model, networks: this.networks}));
            this.renderVerificationControl();
            return this;
        }
    });

    NetworkTabVerificationControl = Backbone.View.extend({
        template: _.template(networkTabVerificationControlTemplate),
        initialize: function(options) {
            _.defaults(this, options);
        },
        render: function() {
            this.$el.html(this.template({cluster: this.model, networks: this.networks}));
            return this;
        }
    });

    return NetworkTab;
});
<|endoftext|>


<commit_before>/* @flow */

import type {
  Logger,
  Config,
  Context,
  Request,
  GSConfig,
  UniversalSettings,
  WebpackConfig,
  CompiledConfig,
} from '../../types';

type RenderMethod = (root: Object, styleTags: Object[]) =>
{ body: string; head: Object[], additionalScripts?: Object[] };

const React = require('react');
const clone = require('clone');
const render = require('../render');

class Index extends React.Component {
  render() {
    return
Index
;
  }
}
// eslint-disable-next-line react/no-multi-comp
class EntryWrapper extends React.Component {
  render() {
    return (

EntryWrapper

    );
  }
}
// eslint-disable-next-line react/no-multi-comp
class BodyWrapper extends React.Component {
  render() {
    return (

BodyWrapper

    );
  }
}

describe('renderer/render', () => {
  const logger: Logger = {
    success: () => {},
    info: () => {},
    warn: () => {},
    debug: () => {},
    error: () => {},
  };

  const gsConfig: GSConfig = {
    protocol: '',
    host: '',
    ports: {
      client: 0,
      server: 0,
    },
    buildAssetsPath: '',
    assetsPath: '',
    sourcePath: '',
    sharedPath: '',
    appsPath: '',
    configPath: '',
    entryWrapperPath: '',
    clientEntryInitPath: '',
    serverEntriesPath: '',
    entriesPath: '',
    reduxMiddlewares: '',
    webpackChunks: '',
    proxyLogLevel: '',
    debugWatchDirectories: [],
    defaultErrorTemplatePath: '',
    customErrorTemplatePath: '',
    autoUpgrade: {
      added: [],
      changed: [],
    },
  };

  const universalSettings: UniversalSettings = {
    server: {
      input: '',
      output: '',
    },
  };

  const client: WebpackConfig = {};
  const server: WebpackConfig = {};

  const webpackConfig: CompiledConfig = {
    universalSettings,
    client,
    server,
  };

  const config: Config = {
    GSConfig: gsConfig,
    webpackConfig,
    plugins: [],
  };

  const entriesPlugins: Function[] = [];

  const context: Context = { config, logger };

  const request: Request = { headers: { 'user-agent': 'Moznota Browser 1.0' }, url: '', hostname: '' };

  const store = {
    getState: jest.fn(() => {}),
  };
  const getRoutes = () => [
    { path: 'hola' },
  ];
  const renderProps = {
    routes: getRoutes(),
  };

  const renderResult = async (email: boolean, cache: boolean, renderMethod):Object => {
    const currentRoute = clone(renderProps);
    currentRoute.email = email;
    currentRoute.cache = cache;
    const results = await render(
      context,
      request,
      { EntryPoint: Index, entryName: 'main', store, routes: getRoutes, httpClient },
      { renderProps, currentRoute },
      { EntryWrapper, BodyWrapper, entryWrapperConfig, envVariables, entriesPlugins },
      { assets, cacheManager },
      { renderMethod });
    return results;
  };

  const checkTest = async (email, cache, renderMethod) => {
    cacheManager.setCacheIfProd.mockReset();
    const results = await renderResult(email, cache, renderMethod);
    if (email) {
      expect(results.rootElement.props.head).toBeNull();
      expect(results.rootElement.props.body.props.html).not.toContain('data-reactid');
      expect(results.rootElement.props.body.props.html).toBeDefined();
    } else {
      expect(results.rootElement.props.head).not.toBeNull();
      if (!renderMethod) {
        expect(results.rootElement.props.body.props.html).toContain('data-reactid');
      }
    }
    if (cache) {
      expect(cacheManager.setCacheIfProd.mock.calls.length).toBe(1);
    } else {
      expect(cacheManager.setCacheIfProd.mock.calls.length).toBe(0);
    }
    expect(results.responseString).toBeDefined();
  };

  const httpClient = {};
  const entryWrapperConfig = {};
  const envVariables = [];
  const assets = {};
  const cacheManager = { setCacheIfProd: jest.fn() };

  describe('without a custom render method and cache set to true', () => {
    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, true);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, true);
      });
    });
  });

  describe('with a custom render method and cache set to true', () => {
    const renderMethod: RenderMethod = (component, styleTags) => {
      expect(component).toBeDefined();
      expect(styleTags).toBeDefined();
      return {
        head: [<meta name="hi" />],
        body: '
That body!
',
      };
    };

    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, true, renderMethod);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, true, renderMethod);
      });
    });
  });

  describe('without a custom render method and cache set to false', () => {
    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, false);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, false);
      });
    });
  });

  describe('with a custom render method and cache set to false', () => {
    const renderMethod: RenderMethod = (component, styleTags) => {
      expect(component).toBeDefined();
      expect(styleTags).toBeDefined();
      return {
        head: [(<meta name="hi" />)],
        body: '
That body!
',
      };
    };

    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, false, renderMethod);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, false, renderMethod);
      });
    });
  });
});
<commit_msg>lint fix<commit_after>/* @flow */

import type {
  Logger,
  Config,
  Context,
  Request,
  GSConfig,
  UniversalSettings,
  WebpackConfig,
  CompiledConfig,
} from '../../types';

type RenderMethod = (root: Object, styleTags: Object[]) =>
  { body: string; head: Object[], additionalScripts?: Object[] };

const React = require('react');
const clone = require('clone');
const render = require('../render');

class Index extends React.Component {
  render() {
    return
Index
;
  }
}
// eslint-disable-next-line react/no-multi-comp
class EntryWrapper extends React.Component {
  render() {
    return (

EntryWrapper

    );
  }
}
// eslint-disable-next-line react/no-multi-comp
class BodyWrapper extends React.Component {
  render() {
    return (

BodyWrapper

    );
  }
}

describe('renderer/render', () => {
  const logger: Logger = {
    success: () => {},
    info: () => {},
    warn: () => {},
    debug: () => {},
    error: () => {},
  };

  const gsConfig: GSConfig = {
    protocol: '',
    host: '',
    ports: {
      client: 0,
      server: 0,
    },
    buildAssetsPath: '',
    assetsPath: '',
    sourcePath: '',
    sharedPath: '',
    appsPath: '',
    configPath: '',
    entryWrapperPath: '',
    clientEntryInitPath: '',
    serverEntriesPath: '',
    entriesPath: '',
    reduxMiddlewares: '',
    webpackChunks: '',
    proxyLogLevel: '',
    debugWatchDirectories: [],
    defaultErrorTemplatePath: '',
    customErrorTemplatePath: '',
    autoUpgrade: {
      added: [],
      changed: [],
    },
  };

  const universalSettings: UniversalSettings = {
    server: {
      input: '',
      output: '',
    },
  };

  const client: WebpackConfig = {};
  const server: WebpackConfig = {};

  const webpackConfig: CompiledConfig = {
    universalSettings,
    client,
    server,
  };

  const config: Config = {
    GSConfig: gsConfig,
    webpackConfig,
    plugins: [],
  };

  const entriesPlugins: Function[] = [];

  const context: Context = { config, logger };

  const request: Request = { headers: { 'user-agent': 'Moznota Browser 1.0' }, url: '', hostname: '' };

  const store = {
    getState: jest.fn(() => {}),
  };
  const getRoutes = () => [
    { path: 'hola' },
  ];
  const renderProps = {
    routes: getRoutes(),
  };

  const renderResult = async (email: boolean, cache: boolean, renderMethod):Object => {
    const currentRoute = clone(renderProps);
    currentRoute.email = email;
    currentRoute.cache = cache;
    const results = await render(
      context,
      request,
      { EntryPoint: Index, entryName: 'main', store, routes: getRoutes, httpClient },
      { renderProps, currentRoute },
      { EntryWrapper, BodyWrapper, entryWrapperConfig, envVariables, entriesPlugins },
      { assets, cacheManager },
      { renderMethod });
    return results;
  };

  const checkTest = async (email, cache, renderMethod) => {
    cacheManager.setCacheIfProd.mockReset();
    const results = await renderResult(email, cache, renderMethod);
    if (email) {
      expect(results.rootElement.props.head).toBeNull();
      expect(results.rootElement.props.body.props.html).not.toContain('data-reactid');
      expect(results.rootElement.props.body.props.html).toBeDefined();
    } else {
      expect(results.rootElement.props.head).not.toBeNull();
      if (!renderMethod) {
        expect(results.rootElement.props.body.props.html).toContain('data-reactid');
      }
    }
    if (cache) {
      expect(cacheManager.setCacheIfProd.mock.calls.length).toBe(1);
    } else {
      expect(cacheManager.setCacheIfProd.mock.calls.length).toBe(0);
    }
    expect(results.responseString).toBeDefined();
  };

  const httpClient = {};
  const entryWrapperConfig = {};
  const envVariables = [];
  const assets = {};
  const cacheManager = { setCacheIfProd: jest.fn() };

  describe('without a custom render method and cache set to true', () => {
    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, true);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, true);
      });
    });
  });

  describe('with a custom render method and cache set to true', () => {
    const renderMethod: RenderMethod = (component, styleTags) => {
      expect(component).toBeDefined();
      expect(styleTags).toBeDefined();
      return {
        head: [<meta name="hi" />],
        body: '
That body!
',
      };
    };

    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, true, renderMethod);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, true, renderMethod);
      });
    });
  });

  describe('without a custom render method and cache set to false', () => {
    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, false);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, false);
      });
    });
  });

  describe('with a custom render method and cache set to false', () => {
    const renderMethod: RenderMethod = (component, styleTags) => {
      expect(component).toBeDefined();
      expect(styleTags).toBeDefined();
      return {
        head: [(<meta name="hi" />)],
        body: '
That body!
',
      };
    };

    describe('when the route is an email route', () => {
      it('should render output', async () => {
        await checkTest(true, false, renderMethod);
      });
    });

    describe('when the route is not an email route', () => {
      it('should render output', async () => {
        await checkTest(false, false, renderMethod);
      });
    });
  });
});
<|endoftext|>