diff --git a/README.md b/README.md index 5b1aa643cf..a66625918d 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,9 @@ If you don't already have `npm`, get it by installing [node.js](http://nodejs.or ### Unit tests -1. `gulp test.unit.js`: JS tests -2. `gulp test.unit.dart`: Dart tests +1. `gulp test.unit.js`: JS tests in a browser +2. `gulp test.unit.cjs`: JS tests in NodeJS (requires a build before) +3. `gulp test.unit.dart`: Dart tests Notes for transpiler tests: diff --git a/gulpfile.js b/gulpfile.js index dfabb414cd..e28a438cee 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -19,6 +19,7 @@ var karma = require('karma').server; var minimist = require('minimist'); var es5build = require('./tools/build/es5build'); var runServerDartTests = require('./tools/build/run_server_dart_tests'); +var transformCJSTests = require('./tools/build/transformCJSTests'); var util = require('./tools/build/util'); var DART_SDK = require('./tools/build/dartdetect')(gulp); @@ -299,12 +300,15 @@ gulp.task('build/transpile.js.prod', function(done) { }); gulp.task('build/transpile.js.cjs', transpile(gulp, gulpPlugins, { - src: CONFIG.transpile.src.js, + src: CONFIG.transpile.src.js.concat(['modules/**/*.cjs']), dest: CONFIG.dest.js.cjs, outputExt: 'js', options: CONFIG.transpile.options.js.cjs, srcFolderInsertion: CONFIG.srcFolderInsertion.js })); +gulp.task('build/transformCJSTests', function() { + return gulp.src(CONFIG.dest.js.cjs + '/angular2/test/**/*_spec.js').pipe(transformCJSTests()).pipe(gulp.dest(CONFIG.dest.js.cjs + '/angular2/test/')); +}); gulp.task('build/transpile.dart', transpile(gulp, gulpPlugins, { src: CONFIG.transpile.src.dart, @@ -548,6 +552,9 @@ gulp.task('test.unit.dart/ci', function (done) { karma.start({configFile: __dirname + '/karma-dart.conf.js', singleRun: true, reporters: ['dots'], browsers: getBrowsersFromCLI()}, done); }); +gulp.task('test.unit.cjs', function (done) { + return gulp.src(CONFIG.dest.js.cjs + '/angular2/test/core/compiler/**/*_spec.js').pipe(jasmine({verbose: true, includeStackTrace: true})); +}); // ------------------ // server tests @@ -616,6 +623,7 @@ gulp.task('build.js.cjs', function(done) { runSequence( ['build/transpile.js.cjs', 'build/copy.js.cjs', 'build/multicopy.js.cjs'], ['build/linknodemodules.js.cjs'], + 'build/transformCJSTests', done ); }); diff --git a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js index 58748d15c7..ec1e8ff939 100644 --- a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js +++ b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js @@ -184,7 +184,9 @@ export class ElementBinderBuilder extends CompileStep { } else { property = this._resolvePropertyName(property); //TODO(pk): special casing innerHtml, see: https://github.com/angular/angular/issues/789 - if (DOM.hasProperty(compileElement.element, property) || StringWrapper.equals(property, 'innerHtml')) { + if (StringWrapper.equals(property, 'innerHTML')) { + setterFn = (element, value) => DOM.setInnerHTML(element, value); + } else if (DOM.hasProperty(compileElement.element, property) || StringWrapper.equals(property, 'innerHtml')) { setterFn = reflector.setter(property); } } diff --git a/modules/angular2/src/dom/parse5_adapter.cjs b/modules/angular2/src/dom/parse5_adapter.cjs new file mode 100644 index 0000000000..3db796ff71 --- /dev/null +++ b/modules/angular2/src/dom/parse5_adapter.cjs @@ -0,0 +1,454 @@ +var parse5 = require('parse5'); +var parser = new parse5.Parser(parse5.TreeAdapters.htmlparser2); +var serializer = new parse5.Serializer(parse5.TreeAdapters.htmlparser2); +var treeAdapter = parser.treeAdapter; + +var cssParse = require('css-parse'); + +var url = require('url'); + +import {List, MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection'; +import {DomAdapter, setRootDomAdapter} from './dom_adapter'; +import {BaseException, isPresent, isBlank} from 'angular2/src/facade/lang'; + +var _attrToPropMap = { + 'inner-html': 'innerHTML', + 'readonly': 'readOnly', + 'tabindex': 'tabIndex', +}; +var defDoc = null; + +function _notImplemented(methodName) { + return new BaseException('This method is not implemented in Parse5DomAdapter: ' + methodName); +} + +export class Parse5DomAdapter extends DomAdapter { + static makeCurrent() { + setRootDomAdapter(new Parse5DomAdapter()); + } + + get attrToPropMap() { + return _attrToPropMap; + } + + query(selector) { + throw _notImplemented('query'); + } + querySelector(el, selector:string) { + throw _notImplemented('querySelector'); + } + querySelectorAll(el, selector:string) { + //TODO: use selector class from core. For now, only works for .classname ... + var res = ListWrapper.create(); + var _recursive = (result, node, className) => { + if (this.hasClass(node, className)) { + ListWrapper.push(result, node); + } + var cNodes = node.childNodes; + if (cNodes && cNodes.length > 0) { + for (var i = 0; i < cNodes.length; i++) { + _recursive(result, cNodes[i], className); + } + } + }; + _recursive(res, el, selector.substring(1)); + return res; + } + on(el, evt, listener) { + throw _notImplemented('on'); + } + dispatchEvent(el, evt) { + throw _notImplemented('dispatchEvent'); + } + createMouseEvent(eventType) { + throw _notImplemented('createMouseEvent'); + } + createEvent(eventType) { + throw _notImplemented('createEvent'); + } + getInnerHTML(el) { + return serializer.serialize(this.templateAwareRoot(el)); + } + getOuterHTML(el) { + serializer.html = ''; + serializer._serializeElement(el); + return serializer.html; + } + nodeName(node):string { + return node.tagName; + } + nodeValue(node):string { + return node.nodeValue; + } + type(node:string) { + throw _notImplemented('type'); + } + content(node) { + return node.childNodes[0]; + } + firstChild(el) { + return el.firstChild; + } + nextSibling(el) { + return el.nextSibling; + } + parentElement(el) { + return el.parent; + } + childNodes(el) { + return el.childNodes; + } + childNodesAsList(el):List { + var childNodes = el.childNodes; + var res = ListWrapper.createFixedSize(childNodes.length); + for (var i = 0; i < childNodes.length; i++) { + res[i] = childNodes[i]; + } + return res; + } + clearNodes(el) { + while (el.childNodes.length > 0) { + this.remove(el.childNodes[0]); + } + } + appendChild(el, node) { + this.remove(node); + treeAdapter.appendChild(this.templateAwareRoot(el), node); + } + removeChild(el, node) { + if (ListWrapper.contains(el.childNodes, node)) { + this.remove(node); + } + } + remove(el) { + var parent = el.parent; + if (parent) { + var index = parent.childNodes.indexOf(el); + parent.childNodes.splice(index, 1); + } + var prev = el.previousSibling; + var next = el.nextSibling; + if (prev) { + prev.next = next; + } + if (next) { + next.prev = prev; + } + el.prev = null; + el.next = null; + el.parent = null; + return el; + } + insertBefore(el, node) { + this.remove(node); + treeAdapter.insertBefore(el.parent, node, el); + } + insertAllBefore(el, nodes) { + ListWrapper.forEach(nodes, (n) => { + this.insertBefore(el, n); + }); + } + insertAfter(el, node) { + if (el.nextSibling) { + this.insertBefore(el.nextSibling, node); + } else { + this.appendChild(el.parent, node); + } + } + setInnerHTML(el, value) { + this.clearNodes(el); + var content = parser.parseFragment(value); + for (var i = 0; i < content.childNodes.length; i++) { + treeAdapter.appendChild(el, content.childNodes[i]); + } + } + getText(el) { + if (this.isTextNode(el)) { + return el.data; + } else if (el.childNodes.length == 0) { + return ""; + } else { + var textContent = ""; + for (var i = 0; i < el.childNodes.length; i++) { + textContent += this.getText(el.childNodes[i]); + } + return textContent; + } + } + setText(el, value:string) { + if (this.isTextNode(el)) { + el.data = value; + } else { + this.clearNodes(el); + treeAdapter.insertText(el, value); + } + } + getValue(el) { + return el.value; + } + setValue(el, value:string) { + el.value = value; + } + getChecked(el) { + return el.checked; + } + setChecked(el, value:boolean) { + el.checked = value; + } + createTemplate(html) { + var template = treeAdapter.createElement("template", 'http://www.w3.org/1999/xhtml', []); + var content = parser.parseFragment(html); + treeAdapter.appendChild(template, content); + return template; + } + createElement(tagName) { + return treeAdapter.createElement(tagName, 'http://www.w3.org/1999/xhtml', []); + } + createTextNode(text: string) { + throw _notImplemented('createTextNode'); + } + createScriptTag(attrName:string, attrValue:string) { + return treeAdapter.createElement("script", 'http://www.w3.org/1999/xhtml', [{name: attrName, value: attrValue}]); + } + createStyleElement(css:string) { + var style = this.createElement('style'); + this.setText(style, css); + return style; + } + createShadowRoot(el) { + el.shadowRoot = treeAdapter.createDocumentFragment(); + el.shadowRoot.parent = el; + return el.shadowRoot; + } + getShadowRoot(el) { + return el.shadowRoot; + } + clone(node) { + var temp = treeAdapter.createElement("template", null, []); + treeAdapter.appendChild(temp, node); + var serialized = serializer.serialize(temp); + var newParser = new parse5.Parser(parse5.TreeAdapters.htmlparser2); + return newParser.parseFragment(serialized).childNodes[0]; + } + hasProperty(element, name:string) { + return _HTMLElementPropertyList.indexOf(name) > -1; + } + getElementsByClassName(element, name:string) { + return this.querySelectorAll(element, "." + name); + } + getElementsByTagName(element, name:string) { + throw _notImplemented('getElementsByTagName'); + } + classList(element):List { + var classAttrValue = null; + var attributes = element.attribs; + if (attributes && attributes.hasOwnProperty("class")) { + classAttrValue = attributes["class"]; + } + return classAttrValue ? classAttrValue.trim().split(/\s+/g) : []; + } + addClass(element, classname:string) { + var classList = this.classList(element); + var index = classList.indexOf(classname); + if (index == -1) { + ListWrapper.push(classList, classname); + element.attribs["class"] = element.className = ListWrapper.join(classList, " "); + } + } + removeClass(element, classname:string) { + var classList = this.classList(element); + var index = classList.indexOf(classname); + if (index > -1) { + classList.splice(index, 1); + element.attribs["class"] = element.className = ListWrapper.join(classList, " "); + } + } + hasClass(element, classname:string) { + return ListWrapper.contains(this.classList(element), classname); + } + _readStyleAttribute(element) { + var styleMap = {}; + var attributes = element.attribs; + if (attributes && attributes.hasOwnProperty("style")) { + var styleAttrValue = attributes["style"]; + var styleList = styleAttrValue.split(/;+/g); + for (var i = 0; i < styleList.length; i++) { + if (styleList[i].length > 0) { + var elems = styleList[i].split(/:+/g); + styleMap[elems[0].trim()] = elems[1].trim(); + } + } + } + return styleMap; + } + _writeStyleAttribute(element, styleMap) { + var styleAttrValue = ""; + for (var key in styleMap) { + var newValue = styleMap[key]; + if (newValue && newValue.length > 0) { + styleAttrValue += key + ":" + styleMap[key] + ";"; + } + } + element.attribs["style"] = styleAttrValue; + } + setStyle(element, stylename:string, stylevalue:string) { + var styleMap = this._readStyleAttribute(element); + styleMap[stylename] = stylevalue; + this._writeStyleAttribute(element, styleMap); + } + removeStyle(element, stylename:string) { + this.setStyle(element, stylename, null); + } + getStyle(element, stylename:string) { + var styleMap = this._readStyleAttribute(element); + return styleMap.hasOwnProperty(stylename) ? styleMap[stylename] : ""; + } + tagName(element):string { + return element.tagName == "style" ? "STYLE" : element.tagName; + } + attributeMap(element) { + var res = MapWrapper.create(); + var elAttrs = treeAdapter.getAttrList(element); + for (var i = 0; i < elAttrs.length; i++) { + var attrib = elAttrs[i]; + MapWrapper.set(res, attrib.name, attrib.value); + } + return res; + } + getAttribute(element, attribute:string) { + return element.attribs.hasOwnProperty(attribute) ? element.attribs[attribute] : null; + } + setAttribute(element, attribute:string, value:string) { + if (attribute) { + element.attribs[attribute] = value; + } + } + removeAttribute(element, attribute:string) { + if (attribute) { + delete element.attribs[attribute]; + } + } + templateAwareRoot(el) { + return this.isTemplateElement(el) ? this.content(el) : el; + } + createHtmlDocument() { + throw _notImplemented('createHtmlDocument'); + } + defaultDoc() { + if (defDoc === null) { + defDoc = StringMapWrapper.create(); + StringMapWrapper.set(defDoc, "head", treeAdapter.createElement("head", null, [])); + } + return defDoc; + } + elementMatches(n, selector:string):boolean { + //TODO: use selector class from core. + if (selector && selector.charAt(0) == ".") { + return this.hasClass(n, selector.substring(1)); + } else { + return n.tagName == selector; + } + } + isTemplateElement(el:any):boolean { + return this.isElementNode(el) && this.tagName(el) === "template"; + } + isTextNode(node):boolean { + return treeAdapter.isTextNode(node); + } + isCommentNode(node):boolean { + throw treeAdapter.isCommentNode(node); + } + isElementNode(node):boolean { + return node ? treeAdapter.isElementNode(node) : false; + } + hasShadowRoot(node):boolean { + return isPresent(node.shadowRoot); + } + importIntoDoc(node) { + return this.clone(node); + } + isPageRule(rule): boolean { + return rule.type === 6; //CSSRule.PAGE_RULE + } + isStyleRule(rule): boolean { + return rule.type === 1; //CSSRule.MEDIA_RULE + } + isMediaRule(rule): boolean { + return rule.type === 4; //CSSRule.MEDIA_RULE + } + isKeyframesRule(rule): boolean { + return rule.type === 7; //CSSRule.KEYFRAMES_RULE + } + getHref(el): string { + return el.href; + } + resolveAndSetHref(el, baseUrl:string, href:string) { + if (href == null) { + el.href = baseUrl; + } else { + el.href = url.resolve(baseUrl, href); + } + } + _buildRules(parsedRules, css) { + var rules = ListWrapper.create(); + for (var i = 0; i < parsedRules.length; i++) { + var parsedRule = parsedRules[i]; + var rule = {cssText: css}; + rule.style = {content: "", cssText: ""}; + if (parsedRule.type == "rule") { + rule.type = 1; + rule.selectorText = parsedRule.selectors.join(", ").replace(/\s{2,}/g, " ").replace(/\s*~\s*/g, " ~ ") + .replace(/\s*\+\s*/g, " + ").replace(/\s*>\s*/g, " > ").replace(/\[(\w+)=(\w+)\]/g, '[$1="$2"]'); + if (isBlank(parsedRule.declarations)) { + continue; + } + for (var j = 0; j < parsedRule.declarations.length; j++) { + var declaration = parsedRule.declarations[j]; + rule.style[declaration.property] = declaration.value; + rule.style.cssText += declaration.property + ": " + declaration.value + ";"; + } + } else if (parsedRule.type == "media") { + rule.type = 4; + rule.media = {mediaText: parsedRule.media}; + if (parsedRule.rules) { + rule.cssRules = this._buildRules(parsedRule.rules); + } + } + ListWrapper.push(rules, rule); + } + return rules; + } + cssToRules(css:string): List { + css = css.replace(/url\(\'(.+)\'\)/g, 'url($1)'); + var rules = ListWrapper.create(); + var parsedCSS = cssParse(css, {silent: true}); + if (parsedCSS.stylesheet && parsedCSS.stylesheet.rules) { + rules = this._buildRules(parsedCSS.stylesheet.rules, css); + } + return rules; + } +} + +//TODO: build a proper list, this one is all the keys of a HTMLInputElement +var _HTMLElementPropertyList = ["webkitEntries","incremental","webkitdirectory","selectionDirection","selectionEnd", +"selectionStart","labels","validationMessage","validity","willValidate","width","valueAsNumber","valueAsDate", +"value","useMap","defaultValue","type","step","src","size","required","readOnly","placeholder","pattern","name", +"multiple","min","minLength","maxLength","max","list","indeterminate","height","formTarget","formNoValidate", +"formMethod","formEnctype","formAction","files","form","disabled","dirName","checked","defaultChecked","autofocus", +"autocomplete","alt","align","accept","onautocompleteerror","onautocomplete","onwaiting","onvolumechange", +"ontoggle","ontimeupdate","onsuspend","onsubmit","onstalled","onshow","onselect","onseeking","onseeked","onscroll", +"onresize","onreset","onratechange","onprogress","onplaying","onplay","onpause","onmousewheel","onmouseup", +"onmouseover","onmouseout","onmousemove","onmouseleave","onmouseenter","onmousedown","onloadstart", +"onloadedmetadata","onloadeddata","onload","onkeyup","onkeypress","onkeydown","oninvalid","oninput","onfocus", +"onerror","onended","onemptied","ondurationchange","ondrop","ondragstart","ondragover","ondragleave","ondragenter", +"ondragend","ondrag","ondblclick","oncuechange","oncontextmenu","onclose","onclick","onchange","oncanplaythrough", +"oncanplay","oncancel","onblur","onabort","spellcheck","isContentEditable","contentEditable","outerText", +"innerText","accessKey","hidden","webkitdropzone","draggable","tabIndex","dir","translate","lang","title", +"childElementCount","lastElementChild","firstElementChild","children","onwebkitfullscreenerror", +"onwebkitfullscreenchange","nextElementSibling","previousElementSibling","onwheel","onselectstart", +"onsearch","onpaste","oncut","oncopy","onbeforepaste","onbeforecut","onbeforecopy","shadowRoot","dataset", +"classList","className","outerHTML","innerHTML","scrollHeight","scrollWidth","scrollTop","scrollLeft", +"clientHeight","clientWidth","clientTop","clientLeft","offsetParent","offsetHeight","offsetWidth","offsetTop", +"offsetLeft","localName","prefix","namespaceURI","id","style","attributes","tagName","parentElement","textContent", +"baseURI","ownerDocument","nextSibling","previousSibling","lastChild","firstChild","childNodes","parentNode", +"nodeType","nodeValue","nodeName","closure_lm_714617","__jsaction"]; diff --git a/modules/angular2/src/test_lib/test_lib.dart b/modules/angular2/src/test_lib/test_lib.dart index 68b81ad007..dfa3557972 100644 --- a/modules/angular2/src/test_lib/test_lib.dart +++ b/modules/angular2/src/test_lib/test_lib.dart @@ -11,6 +11,7 @@ import 'package:collection/equality.dart'; import 'package:angular2/src/dom/dom_adapter.dart' show DOM; bool IS_DARTIUM = true; +bool IS_NODEJS = false; Expect expect(actual, [matcher]) { final expect = new Expect(actual); diff --git a/modules/angular2/src/test_lib/test_lib.es6 b/modules/angular2/src/test_lib/test_lib.es6 index 033bd5d187..3abdbcaac0 100644 --- a/modules/angular2/src/test_lib/test_lib.es6 +++ b/modules/angular2/src/test_lib/test_lib.es6 @@ -1,23 +1,26 @@ import {DOM} from 'angular2/src/dom/dom_adapter'; +var _global = typeof window === 'undefined' ? global : window; + export {proxy} from 'rtts_assert/rtts_assert'; -export var describe = window.describe; -export var xdescribe = window.xdescribe; -export var ddescribe = window.ddescribe; -export var it = window.it; -export var xit = window.xit; -export var iit = window.iit; -export var beforeEach = window.beforeEach; -export var afterEach = window.afterEach; -export var expect = window.expect; +export var describe = _global.describe; +export var xdescribe = _global.xdescribe; +export var ddescribe = _global.ddescribe; +export var it = _global.it; +export var xit = _global.xit; +export var iit = _global.iit; +export var beforeEach = _global.beforeEach; +export var afterEach = _global.afterEach; +export var expect = _global.expect; export var IS_DARTIUM = false; +export var IS_NODEJS = typeof window === 'undefined'; // To make testing consistent between dart and js -window.print = function(msg) { - if (window.dump) { - window.dump(msg); +_global.print = function(msg) { + if (_global.dump) { + _global.dump(msg); } else { - window.console.log(msg); + _global.console.log(msg); } }; @@ -25,7 +28,7 @@ window.print = function(msg) { // gives us bad error messages in tests. // The only way to do this in Jasmine is to monkey patch a method // to the object :-( -window.Map.prototype.jasmineToString = function() { +_global.Map.prototype.jasmineToString = function() { var m = this; if (!m) { return ''+m; @@ -37,7 +40,7 @@ window.Map.prototype.jasmineToString = function() { return `{ ${res.join(',')} }`; } -window.beforeEach(function() { +_global.beforeEach(function() { jasmine.addMatchers({ // Custom handler for Map as Jasmine does not support it yet toEqual: function(util, customEqualityTesters) { @@ -150,15 +153,48 @@ export class SpyObject { function elementText(n) { - var hasNodes = (n) => {var children = DOM.childNodes(n); return children && children.length > 0;} + if (!IS_NODEJS) { + var hasNodes = (n) => {var children = DOM.childNodes(n); return children && children.length > 0;} - if (n instanceof Comment) return ''; + if (n instanceof Comment) return ''; - if (n instanceof Array) return n.map((nn) => elementText(nn)).join(""); - if (n instanceof Element && DOM.tagName(n) == 'CONTENT') - return elementText(Array.prototype.slice.apply(n.getDistributedNodes())); - if (DOM.hasShadowRoot(n)) return elementText(DOM.childNodesAsList(n.shadowRoot)); - if (hasNodes(n)) return elementText(DOM.childNodesAsList(n)); + if (n instanceof Array) return n.map((nn) => elementText(nn)).join(""); + if (n instanceof Element && DOM.tagName(n) == 'CONTENT') + return elementText(Array.prototype.slice.apply(n.getDistributedNodes())); + if (DOM.hasShadowRoot(n)) return elementText(DOM.childNodesAsList(n.shadowRoot)); + if (hasNodes(n)) return elementText(DOM.childNodesAsList(n)); - return n.textContent; + return n.textContent; + } else { + if (DOM.hasShadowRoot(n)) { + return elementText(DOM.getShadowRoot(n).childNodes); + } else if (n instanceof Array) { + return n.map((nn) => elementText(nn)).join(""); + } else if (DOM.tagName(n) == 'content') { + //minimal implementation of getDistributedNodes() + var host = null; + var temp = n; + while (temp.parent) { + if (DOM.hasShadowRoot(temp)) { + host = temp; + } + temp = temp.parent; + } + if (host) { + var list = []; + var select = DOM.getAttribute(n, "select"); + var selectClass = select? select.substring(1): null; + DOM.childNodes(host).forEach((child) => { + var classList = DOM.classList(child); + if (selectClass && classList.indexOf(selectClass) > -1 || selectClass == null && classList.length == 0) { + list.push(child); + } + }); + return list.length > 0? elementText(list): ""; + } + return ""; + } else { + return DOM.getText(n); + } + } } diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index 58cc788269..c39ddab401 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -19,10 +19,6 @@ import {UrlResolver} from 'angular2/src/core/compiler/url_resolver'; import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver'; import {CssProcessor} from 'angular2/src/core/compiler/css_processor'; -import {EventManager, DomEventsPlugin} from 'angular2/src/core/events/event_manager'; - -import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone'; - import {Decorator, Component, Viewport} from 'angular2/src/core/annotations/annotations'; import {Template} from 'angular2/src/core/annotations/template'; import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility'; @@ -64,7 +60,7 @@ export function main() { ctx = new MyComp(); view = pv.instantiate( null, - new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()), + null, reflector ); view.hydrate(new Injector([]), null, ctx); @@ -354,7 +350,7 @@ export function main() { var value = view.contextWithLocals.get('alice'); expect(value).not.toBe(null); - expect(value.tagName).toEqual('DIV'); + expect(value.tagName.toLowerCase()).toEqual('div'); done(); }) @@ -724,18 +720,3 @@ class DecoratorListeningEvent { this.msg = msg; } } - -class FakeVmTurnZone extends VmTurnZone { - constructor() { - super({enableLongStackTrace: false}); - } - - run(fn) { - fn(); - } - - runOutsideAngular(fn) { - fn(); - } -} - diff --git a/modules/angular2/test/core/compiler/shadow_dom/shadow_css_spec.js b/modules/angular2/test/core/compiler/shadow_dom/shadow_css_spec.js index 5439683b0c..2cbbe4732b 100644 --- a/modules/angular2/test/core/compiler/shadow_dom/shadow_css_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom/shadow_css_spec.js @@ -1,4 +1,4 @@ -import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el} from 'angular2/test_lib'; +import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, IS_NODEJS} from 'angular2/test_lib'; import {ShadowCss} from 'angular2/src/core/compiler/shadow_dom_emulation/shadow_css'; import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang'; @@ -91,13 +91,16 @@ export function main() { expect(StringWrapper.contains(css, '#menu > .bar {;background: blue;}')).toBeTruthy(); }); - it('should support polyfill-rule', () => { - var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a', 'a-host'); - expect(css).toEqual('[a-host].foo .bar {background: blue;}'); + if (!IS_NODEJS) { + //TODO: reactivate once CSS parser is fixed: https://github.com/reworkcss/css/issues/65 + it('should support polyfill-rule', () => { + var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a', 'a-host'); + expect(css).toEqual('[a-host].foo .bar {background: blue;}'); - css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a', 'a-host'); - expect(css).toEqual('[a-host].foo .bar {background: blue;}'); - }); + css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a', 'a-host'); + expect(css).toEqual('[a-host].foo .bar {background: blue;}'); + }); + } it('should handle ::shadow', () => { var css = s('x::shadow > y {}', 'a'); diff --git a/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js b/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js index 44a26ee75c..470355e7f0 100644 --- a/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js @@ -87,7 +87,7 @@ export function main() { strategy.attachTemplate(host, view); var firstChild = DOM.firstChild(host); - expect(DOM.tagName(firstChild)).toEqual('DIV'); + expect(DOM.tagName(firstChild).toLowerCase()).toEqual('div'); expect(firstChild).toHaveText('view'); expect(host).toHaveText('view'); }); @@ -222,7 +222,7 @@ export function main() { strategy.attachTemplate(host, view); var firstChild = DOM.firstChild(host); - expect(DOM.tagName(firstChild)).toEqual('DIV'); + expect(DOM.tagName(firstChild).toLowerCase()).toEqual('div'); expect(firstChild).toHaveText('view'); expect(host).toHaveText('view'); }); diff --git a/modules/angular2/test/core/compiler/view_spec.js b/modules/angular2/test/core/compiler/view_spec.js index 74027c5ac7..e4eac84a7d 100644 --- a/modules/angular2/test/core/compiler/view_spec.js +++ b/modules/angular2/test/core/compiler/view_spec.js @@ -1,4 +1,4 @@ -import {describe, xit, it, expect, beforeEach, ddescribe, iit, el, proxy} from 'angular2/test_lib'; +import {describe, xit, it, expect, beforeEach, ddescribe, iit, el, proxy, IS_NODEJS} from 'angular2/test_lib'; import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'angular2/src/core/compiler/view'; import {ProtoElementInjector, ElementInjector, DirectiveBinding} from 'angular2/src/core/compiler/element_injector'; import {EmulatedScopedShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy'; @@ -444,96 +444,98 @@ export function main() { }); }); - describe('event handlers', () => { - var view, ctx, called, receivedEvent, dispatchedEvent; + if (!IS_NODEJS) { + describe('event handlers', () => { + var view, ctx, called, receivedEvent, dispatchedEvent; - function createViewAndContext(protoView) { - view = createView(protoView, - new EventManager([new DomEventsPlugin()], new FakeVmTurnZone())); - ctx = view.context; - called = 0; - receivedEvent = null; - ctx.callMe = (event) => { - called += 1; - receivedEvent = event; + function createViewAndContext(protoView) { + view = createView(protoView, + new EventManager([new DomEventsPlugin()], new FakeVmTurnZone())); + ctx = view.context; + called = 0; + receivedEvent = null; + ctx.callMe = (event) => { + called += 1; + receivedEvent = event; + } } - } - function dispatchClick(el) { - dispatchedEvent = DOM.createMouseEvent('click'); - DOM.dispatchEvent(el, dispatchedEvent); - } + function dispatchClick(el) { + dispatchedEvent = DOM.createMouseEvent('click'); + DOM.dispatchEvent(el, dispatchedEvent); + } - function createProtoView() { - var pv = new ProtoView(el('