diff options
| -rw-r--r-- | Rakefile | 7 | ||||
| -rw-r--r-- | css/angular-scenario.css | 40 | ||||
| -rw-r--r-- | scenario/widgets-scenario.js | 17 | ||||
| -rw-r--r-- | scenario/widgets.html | 2 | ||||
| -rw-r--r-- | src/Angular.js | 4 | ||||
| -rw-r--r-- | src/jqLite.js | 11 | ||||
| -rw-r--r-- | src/scenario/Scenario.js | 49 | ||||
| -rw-r--r-- | src/scenario/SpecRunner.js | 34 | ||||
| -rw-r--r-- | src/scenario/angular.prefix | 1 | ||||
| -rw-r--r-- | src/scenario/angular.suffix | 13 | ||||
| -rw-r--r-- | src/scenario/bootstrap.js | 8 | ||||
| -rwxr-xr-x | test.sh | 4 | ||||
| -rw-r--r-- | test/BinderTest.js | 4 | ||||
| -rw-r--r-- | test/scenario/dslSpec.js | 42 | ||||
| -rw-r--r-- | test/testabilityPatch.js | 19 | ||||
| -rw-r--r-- | test/widgetsSpec.js | 16 | 
16 files changed, 119 insertions, 152 deletions
| @@ -53,7 +53,7 @@ end  desc 'Compile Scenario'  task :compile_scenario do -   +    deps = [        'lib/jquery/jquery-1.4.2.js',        'src/scenario/angular.prefix', @@ -66,7 +66,7 @@ task :compile_scenario do    File.open('angular-scenario.js', 'w') do |f|      f.write(%x{#{concat}}) -    f.write(gen_css('css/angular.css')) +    f.write(gen_css('css/angular.css') + "\n")      f.write(gen_css('css/angular-scenario.css'))    end  end @@ -234,7 +234,8 @@ def gen_css(cssFile, minify = false)    end    #escape for js -  css.gsub! /'/, "\\'" +  css.gsub! /\\/, "\\\\\\" +  css.gsub! /'/, "\\\\'"    css.gsub! /\n/, "\\n"    return %Q{document.write('<style type="text/css">#{css}</style>');} diff --git a/css/angular-scenario.css b/css/angular-scenario.css index 2cf24b19..3462ecef 100644 --- a/css/angular-scenario.css +++ b/css/angular-scenario.css @@ -38,15 +38,15 @@ body {    padding: 0.5em;    font-size: 1.1em;  } -       +  #status-legend {    margin-top: 10px;    margin-right: 10px;  } -#header,  +#header,  #frame, -.test-info,  +.test-info,  .test-actions li {    overflow: hidden;  } @@ -67,10 +67,10 @@ body {  #frame iframe {    border: none;  } -       -.tests li,  + +.tests li,  .test-actions li, -.test-it li,  +.test-it li,  .test-it ol,  .status-display {    list-style-type: none; @@ -83,14 +83,14 @@ body {    padding: 0;  } -.test-info {  +.test-info {    margin-left: 1em;    margin-top: 0.5em;    border-radius: 8px 0 0 8px;    -webkit-border-radius: 8px 0 0 8px;    -moz-border-radius: 8px 0 0 8px;  } -                   +  .test-it ol {    margin-left: 2.5em;  } @@ -104,7 +104,7 @@ body {    padding: 5px 10px;  } -.timer-result,  +.timer-result,  .test-title {    display: inline-block;    margin: 0; @@ -129,7 +129,7 @@ body {  }  .test-actions .status-pending .test-title:before { -  content: 'ยป '; +  content: '\00bb\00A0';  }  /** Colors */ @@ -150,7 +150,7 @@ body {  #frame {    border: 1px solid #BABAD1;  } -       +  .test-describe .test-describe {    border-left: 1px solid #BABAD1;    border-right: 1px solid #BABAD1; @@ -168,29 +168,29 @@ body {  .status-display .status-success,  .status-success .test-info { -  background-color: #B1D7A1;  +  background-color: #B1D7A1;  } -       +  .status-display .status-failure, -.status-failure .test-info {  -  background-color: #FF8286;  +.status-failure .test-info { +  background-color: #FF8286;  }  .status-display .status-error, -.status-error .test-info {  +.status-error .test-info {    background-color: black;    color: white;  } -.test-actions .status-success .test-title {  -  color: #30B30A;  +.test-actions .status-success .test-title { +  color: #30B30A;  } -.test-actions .status-failure .test-title {  +.test-actions .status-failure .test-title {    color: #DF0000;  } -.test-actions .status-error .test-title {  +.test-actions .status-error .test-title {    color: black;  } diff --git a/scenario/widgets-scenario.js b/scenario/widgets-scenario.js index befc481c..0cb189f7 100644 --- a/scenario/widgets-scenario.js +++ b/scenario/widgets-scenario.js @@ -1,17 +1,17 @@  describe('widgets', function() {    it('should verify that basic widgets work', function(){      navigateTo('widgets.html'); -             +      using('#text-basic-box').input('text.basic').enter('Carlos');      expect(binding('text.basic')).toEqual('Carlos');      input('text.basic').enter('Carlos Santana');      expect(binding('text.basic')).not().toEqual('Carlos Boozer'); -     +      input('text.password').enter('secret');      expect(binding('text.password')).toEqual('secret'); -     +      expect(binding('text.hidden')).toEqual('hiddenValue'); -     +      expect(binding('gender')).toEqual('male');      input('gender').select('female');      expect(using('#gender-box').binding('gender')).toEqual('female'); @@ -19,10 +19,11 @@ describe('widgets', function() {      expect(repeater('#repeater-row ul li').count()).toEqual(2);      expect(repeater('#repeater-row ul li').row(1)).toEqual(['adam']);      expect(repeater('#repeater-row ul li').column('name')).toEqual(['misko', 'adam']); -     +      select('select').option('B');      expect(binding('select')).toEqual('B'); -     + +      select('multiselect').options('A', 'C');      expect(binding('multiselect').fromJson()).toEqual(['A', 'C']); @@ -35,14 +36,14 @@ describe('widgets', function() {      expect(binding('button').fromJson()).toEqual({'count': 3});      element('input[type="image"]').click();      expect(binding('button').fromJson()).toEqual({'count': 4}); -     +      /**       * Custom value parser for futures.       */      function checkboxParser(value) {        return angular.fromJson(value.substring(value.indexOf('=')+1));      } -     +      input('checkbox.tea').check();      expect(binding('checkbox').parsedWith(checkboxParser)).toEqual({coffee: false, tea: false});      input('checkbox.coffee').check(); diff --git a/scenario/widgets.html b/scenario/widgets.html index 80a0a22f..8960f5f4 100644 --- a/scenario/widgets.html +++ b/scenario/widgets.html @@ -2,7 +2,7 @@  <html xmlns:ng="http://angularjs.org">    <head>      <link rel="stylesheet" type="text/css" href="style.css"/> -    <script type="text/javascript" src="../lib/jquery/jquery-1.4.2.js"></script> +    <script type="text/javascript" src="../libs/jquery/jquery-1.4.2.js"></script>      <script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>    </head>    <body ng:init="$window.$scope = this"> diff --git a/src/Angular.js b/src/Angular.js index 8cacb9e4..b97c4226 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -146,12 +146,12 @@ function HTML(html) {  if (msie) {    nodeName = function(element) { -    element = element[0] || element; +    element = element.nodeName ? element : element[0];      return (element.scopeName && element.scopeName != 'HTML' ) ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;    };  } else {    nodeName = function(element) { -    return (element[0] || element).nodeName; +    return element.nodeName ? element.nodeName : element[0].nodeName;    };  } diff --git a/src/jqLite.js b/src/jqLite.js index a2ea286b..6c70f2a8 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -118,17 +118,6 @@ JQLite.prototype = {      });    }, -  trigger: function(type) { -    if (msie) { -      this[0].fireEvent('on' + type); -    } else { -      var evnt = document.createEvent('MouseEvents'), -          element = this[0]; -      evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element); -      element.dispatchEvent(evnt); -    } -  }, -    replaceWith: function(replaceNode) {      this[0].parentNode.replaceChild(jqLite(replaceNode)[0], this[0]);    }, diff --git a/src/scenario/Scenario.js b/src/scenario/Scenario.js index e93f6b2e..ba206632 100644 --- a/src/scenario/Scenario.js +++ b/src/scenario/Scenario.js @@ -1,5 +1,5 @@  /** - * Setup file for the Scenario.  + * Setup file for the Scenario.   * Must be first in the compilation/bootstrap list.   */ @@ -19,7 +19,7 @@ angular.scenario.ui = {};   *   functions.   *   * @param {String} The name of the statement - * @param {Function} Factory function(application), return a function for  + * @param {Function} Factory function(application), return a function for   *  the statement.   */  angular.scenario.dsl = function(name, fn) { @@ -50,7 +50,7 @@ angular.scenario.dsl = function(name, fn) {  /**   * Defines a new matcher for use with the expects() statement. The value - * this.actual (like in Jasmine) is available in your matcher to compare  + * this.actual (like in Jasmine) is available in your matcher to compare   * against. Your function should return a boolean. The future is automatically   * created for you.   * @@ -83,7 +83,7 @@ angular.scenario.matcher = function(name, fn) {   *   * @param {Array} list to iterate over   * @param {Function} Callback function(value, continueFunction) - * @param {Function} Callback function(error, result) called when iteration  + * @param {Function} Callback function(error, result) called when iteration   *   finishes or an error occurs.   */  function asyncForEach(list, iterator, done) { @@ -101,3 +101,44 @@ function asyncForEach(list, iterator, done) {    }    loop();  } + + +function browserTrigger(element, type) { +  if (!element.nodeName) element = element[0]; +  if (!type) { +    type = { +        'text':            'change', +        'textarea':        'change', +        'hidden':          'change', +        'password':        'change', +        'button':          'click', +        'submit':          'click', +        'reset':           'click', +        'image':           'click', +        'checkbox':        'click', +        'radio':           'click', +        'select-one':      'change', +        'select-multiple': 'change' +    }[element.type] || 'click'; +  } +  if (lowercase(nodeName(element)) == 'option') { +    element.parentNode.value = element.value; +    element = element.parentNode; +    type = 'change'; +  } +  if (msie) { +    element.fireEvent('on' + type); +  } else { +    var evnt = document.createEvent('MouseEvents'); +    evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element); +    element.dispatchEvent(evnt); +  } +} + +_jQuery.fn.trigger = function(type) { +  return this.each(function(index, node) { +    browserTrigger(node, type); +  }); +}; + + diff --git a/src/scenario/SpecRunner.js b/src/scenario/SpecRunner.js index d6cbdcdc..26fa9b91 100644 --- a/src/scenario/SpecRunner.js +++ b/src/scenario/SpecRunner.js @@ -21,7 +21,7 @@ angular.scenario.SpecRunner = function() {   */  angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {    var specUI = ui.addSpec(spec); -   +    try {      spec.fn.call(this);    } catch (e) { @@ -29,9 +29,9 @@ angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {      specDone();      return;    } -   +    asyncForEach( -    this.futures,  +    this.futures,      function(future, futureDone) {        var stepUI = specUI.addStep(future.name);        try { @@ -43,10 +43,10 @@ angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {          stepUI.error(e);          throw e;        } -    },  +    },      function(e) { -      specUI.finish(e);  -      specDone();  +      specUI.finish(e); +      specDone();      }    );  }; @@ -89,29 +89,9 @@ angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior)            };          } -        result.trigger = function(type) { -          result.each(function(index, node) { -            var element = $window.angular.element(node); -            //TODO(esprehn): HACK!!! Something is broken in angular event dispatching -            //  and if the real jQuery is used we need to set the attribtue after too -            if (angular.isDefined(element.selector)) { -              if (type === 'click' && node.nodeName.toLowerCase() === 'input') { -                element.attr('checked', !element.attr('checked')); -              } -            } -            //TODO(esprehn): HACK!! See above comment. -            element.trigger(type); -            if (angular.isDefined(element.selector)) { -              if (type === 'click' && node.nodeName.toLowerCase() === 'input') { -                element.attr('checked', !element.attr('checked')); -              } -            } -          }); -        }; -          return result;        }); -       +        try {          behavior.call(this, $window, $document, done);        } catch(e) { diff --git a/src/scenario/angular.prefix b/src/scenario/angular.prefix index a1b4e151..d6660d61 100644 --- a/src/scenario/angular.prefix +++ b/src/scenario/angular.prefix @@ -22,3 +22,4 @@   * THE SOFTWARE.   */  (function(window, document, previousOnLoad){ +  var _jQuery = window.jQuery.noConflict(true);
\ No newline at end of file diff --git a/src/scenario/angular.suffix b/src/scenario/angular.suffix index 53d99dd2..c38f0ab5 100644 --- a/src/scenario/angular.suffix +++ b/src/scenario/angular.suffix @@ -4,22 +4,19 @@      try {        if (previousOnLoad) previousOnLoad();      } catch(e) {} -    jQuery(document.body).append( +    _jQuery(document.body).append(        '<div id="runner"></div>' +        '<div id="frame"></div>'      ); -    var frame = jQuery('#frame'); -    var runner = jQuery('#runner'); +    var frame = _jQuery('#frame'); +    var runner = _jQuery('#runner');      var application = new angular.scenario.Application(frame);      var ui = new angular.scenario.ui.Html(runner); -    $scenario.run(ui, application, function(error) { +    $scenario.run(ui, application, angular.scenario.SpecRunner, function(error) {        frame.remove();        if (error) {          if (window.console) { -          console.log(error); -          if (error.stack) { -            console.log(error.stack); -          } +          console.log(error.stack || error);          } else {            // Do something for IE            alert(error); diff --git a/src/scenario/bootstrap.js b/src/scenario/bootstrap.js index 014c636d..4661bfb2 100644 --- a/src/scenario/bootstrap.js +++ b/src/scenario/bootstrap.js @@ -10,7 +10,7 @@        }      }    })(); -   +    function addScript(path) {      document.write('<script type="text/javascript" src="' + prefix + path + '"></script>');    } @@ -46,6 +46,11 @@    addCSS("../../css/angular-scenario.css");    addScript("../../lib/jquery/jquery-1.4.2.js"); +  document.write( +      '<script type="text/javascript">' + +      'var _jQuery = jQuery.noConflict(true);' + +      '</script>' +    );    addScript("../angular-bootstrap.js");    addScript("Scenario.js"); @@ -61,7 +66,6 @@    // Create the runner (which also sets up the global API)    document.write(      '<script type="text/javascript">' + -    'var _jQuery = jQuery.noConflict(true);' +      'var $scenario = new angular.scenario.Runner(window);' +      '</script>'    ); @@ -3,5 +3,5 @@ if [[ $tests = "" ]]; then    tests="all"  fi -java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" -#java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" --config jsTestDriver-jquery.conf +#java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" +java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" --config jsTestDriver-jquery.conf diff --git a/test/BinderTest.js b/test/BinderTest.js index 5d72206d..daaaeffe 100644 --- a/test/BinderTest.js +++ b/test/BinderTest.js @@ -589,13 +589,13 @@ BinderTest.prototype.testItShouldSelectTheCorrectRadioBox = function() {    var female = jqLite(c.node[0].childNodes[0]);    var male = jqLite(c.node[0].childNodes[1]); -  click(female); +  browserTrigger(female);    assertEquals("female", c.scope.sex);    assertEquals(true, female[0].checked);    assertEquals(false, male[0].checked);    assertEquals("female", female.val()); -  click(male); +  browserTrigger(male);    assertEquals("male", c.scope.sex);    assertEquals(false, female[0].checked);    assertEquals(true, male[0].checked); diff --git a/test/scenario/dslSpec.js b/test/scenario/dslSpec.js index a30fe165..dd489d86 100644 --- a/test/scenario/dslSpec.js +++ b/test/scenario/dslSpec.js @@ -10,24 +10,6 @@ AngularMock.prototype.reset = function() {    this.log = [];  }; -AngularMock.prototype.element = function(node) { -  this.log.push('element(' + node.nodeName.toLowerCase() + ')'); -  var mock = this; -  return { -    selector: '', -    attr: function(name, value) { -      mock.log.push('attr(' + name + (angular.isDefined(value) ? ',' + value : '') + ')'); -      return _jQuery.fn.attr.apply(_jQuery(node), arguments);  -    }, -    trigger: function(type) { -      mock.log.push('element().trigger(' + type + ')'); -      //TODO(esprehn): See the HACK!! in the SpecRunner. This avoids -      // triggering the second part of the hack in tests -      delete this.selector; -    } -  }; -}; -  AngularMock.prototype.$browser = function() {    this.log.push('$brower()');    return this; @@ -181,7 +163,7 @@ describe("angular.scenario.dsl", function() {          $root.dsl.select('test').options('A', 'B');          expect(_jQuery('[name="test"]').val()).toEqual(['A','B']);        }); -       +        it('should fail to select multiple options on non-multiple select', function() {          doc.append('<select name="test"></select>');          $root.dsl.select('test').options('A', 'B'); @@ -198,7 +180,7 @@ describe("angular.scenario.dsl", function() {          });          $root.dsl.element('a').click();        }); -       +        it('should get attribute', function() {          doc.append('<div id="test" class="foo"></div>');          $root.dsl.element('#test').attr('class'); @@ -210,13 +192,13 @@ describe("angular.scenario.dsl", function() {          $root.dsl.element('#test').attr('class', 'bam');          expect(doc.find('div').attr('class')).toEqual('bam');        }); -       +        it('should get val', function() {          doc.append('<input value="bar">');          $root.dsl.element('input').val();          expect($root.futureResult).toEqual('bar');        }); -       +        it('should set val', function() {          doc.append('<input value="bar">');          $root.dsl.element('input').val('baz'); @@ -259,7 +241,7 @@ describe("angular.scenario.dsl", function() {          $root.dsl.binding('foo.bar');          expect($root.futureResult).toEqual('some value');        }); -       +        it('should select binding in template by name', function() {          doc.append('<pre ng:bind-template="foo {{bar}} baz">foo some baz</pre>');          $root.dsl.binding('bar'); @@ -271,7 +253,7 @@ describe("angular.scenario.dsl", function() {          expect($root.futureError).toMatch(/did not match/);        });      }); -     +      describe('Using', function() {        it('should prefix selector in $document.elements()', function() {          var chain; @@ -281,8 +263,6 @@ describe("angular.scenario.dsl", function() {          );          chain = $root.dsl.using('div#test2');          chain.input('test.input').enter('foo'); -        expect($window.angular.log).toContain('element(input)'); -        expect($window.angular.log).toContain('element().trigger(change)');          var inputs = _jQuery('input[name="test.input"]');          expect(inputs.first().val()).toEqual('something');          expect(inputs.last().val()).toEqual('foo'); @@ -294,8 +274,6 @@ describe("angular.scenario.dsl", function() {          doc.append('<input name="test.input" value="something">');          var chain = $root.dsl.input('test.input');          chain.enter('foo'); -        expect($window.angular.log).toContain('element(input)'); -        expect($window.angular.log).toContain('element().trigger(change)');          expect(_jQuery('input[name="test.input"]').val()).toEqual('foo');        }); @@ -311,14 +289,10 @@ describe("angular.scenario.dsl", function() {            attr('checked')).toBeTruthy();          var chain = $root.dsl.input('test.input');          chain.check(); -        expect($window.angular.log).toContain('element(input)'); -        expect($window.angular.log).toContain('element().trigger(click)');          expect(_jQuery('input[name="test.input"]').            attr('checked')).toBeFalsy();          $window.angular.reset();          chain.check(); -        expect($window.angular.log).toContain('element(input)'); -        expect($window.angular.log).toContain('element().trigger(click)');          expect(_jQuery('input[name="test.input"]').            attr('checked')).toBeTruthy();        }); @@ -342,8 +316,6 @@ describe("angular.scenario.dsl", function() {            attr('checked')).toBeFalsy();          var chain = $root.dsl.input('test.input');          chain.select('foo'); -        expect($window.angular.log).toContain('element(input)'); -        expect($window.angular.log).toContain('element().trigger(click)');          expect(_jQuery('input[name="0@test.input"][value="bar"]').            attr('checked')).toBeFalsy();          expect(_jQuery('input[name="0@test.input"][value="foo"]'). @@ -356,6 +328,6 @@ describe("angular.scenario.dsl", function() {          expect($root.futureError).toMatch(/did not match/);        });      }); -     +    });  }); diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js index 59d8f4ac..247faa19 100644 --- a/test/testabilityPatch.js +++ b/test/testabilityPatch.js @@ -189,25 +189,6 @@ function assertThrows(error, fn){  log = noop;  error = noop; -function click(element) { -  element = jqLite(element); -  var type = lowercase(element.attr('type')); -  var name = lowercase(nodeName(element)); -  if (msie) { -    if (name == 'input') { -      if (type == 'radio' || type == 'checkbox') { -        element[0].checked = ! element[0].checked; -      } -    } -  } -  if (name == 'option') { -    element.parent().val(element.val()); -    JQLite.prototype.trigger.call(element.parent(), 'change'); -  } else { -    JQLite.prototype.trigger.call(element, 'click'); -  } -} -  function rethrow(e) {    if(e) {      throw e; diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 31596a48..cc254eff 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -128,10 +128,10 @@ describe("widget", function(){          it('should support type="checkbox"', function(){            compile('<input type="checkBox" name="checkbox" checked ng:change="action = true"/>');            expect(scope.checkbox).toEqual(true); -          click(element); +          browserTrigger(element);            expect(scope.checkbox).toEqual(false);            expect(scope.action).toEqual(true); -          click(element); +          browserTrigger(element);            expect(scope.checkbox).toEqual(true);          }); @@ -151,7 +151,7 @@ describe("widget", function(){            expect(scope.state).toEqual("Worked");            expect(scope.$element[0].checked).toEqual(true); -          click(scope.$element); +          browserTrigger(scope.$element);            expect(scope.state).toEqual("Failed");            expect(scope.$element[0].checked).toEqual(false); @@ -278,13 +278,13 @@ describe("widget", function(){      it('should call ng:change on button click', function(){        compile('<input type="button" value="Click Me" ng:change="clicked = true"/>'); -      click(element); +      browserTrigger(element);        expect(scope.$get('clicked')).toEqual(true);      });      it('should support button alias', function(){        compile('<button ng:change="clicked = true">Click Me</button>'); -      click(element); +      browserTrigger(element);        expect(scope.$get('clicked')).toEqual(true);      }); @@ -310,7 +310,7 @@ describe("widget", function(){          expect(b.checked).toEqual(true);          expect(scope.clicked).not.toBeDefined(); -        click(a); +        browserTrigger(a);          expect(scope.chose).toEqual('A');          expect(scope.clicked).toEqual(1);        }); @@ -363,7 +363,7 @@ describe("widget", function(){          // childNodes[0] is repeater comment          expect(scope.selection).toEqual(undefined); -        click(element[0].childNodes[2]); +        browserTrigger(element[0].childNodes[2], 'change');          expect(scope.selection).toEqual(1);          scope.selection = 2; @@ -423,7 +423,7 @@ describe("widget", function(){      it('should report error on ng:change exception', function(){        compile('<button ng:change="a-2=x">click</button>'); -      click(element); +      browserTrigger(element);        expect(element.hasClass('ng-exception')).toBeTruthy();      });    }); | 
