diff --git a/gulpfile.js b/gulpfile.js index 5966f5c4fa..5ccd8e37b2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -215,7 +215,6 @@ var CONFIG = { }; CONFIG.test.js.cjs = CONFIG.test.js.cjs.map(function(s) {return CONFIG.dest.js.cjs + s}); CONFIG.test.js.cjs.push('!**/core/zone/vm_turn_zone_spec.js'); //Disabled in nodejs because it relies on Zone.js -CONFIG.test.js.cjs.push('!**/render/dom/events/event_manager_spec.js'); //Disabled in nodejs because it relies on DOM events // ------------ // clean diff --git a/modules/angular2/src/dom/parse5_adapter.cjs b/modules/angular2/src/dom/parse5_adapter.cjs index 96c34394d4..df7e4b1ff1 100644 --- a/modules/angular2/src/dom/parse5_adapter.cjs +++ b/modules/angular2/src/dom/parse5_adapter.cjs @@ -84,19 +84,46 @@ export class Parse5DomAdapter extends DomAdapter { return result; } on(el, evt, listener) { - //Do nothing, in order to not break forms integration tests + var listenersMap = el._eventListenersMap; + if (isBlank(listenersMap)) { + var listenersMap = StringMapWrapper.create(); + el._eventListenersMap = listenersMap; + } + var listeners = StringMapWrapper.get(listenersMap, evt); + if (isBlank(listeners)) { + listeners = ListWrapper.create(); + } + ListWrapper.push(listeners, listener); + StringMapWrapper.set(listenersMap, evt, listeners); } onAndCancel(el, evt, listener): Function { - //Do nothing, in order to not break forms integration tests + this.on(el, evt, listener); + return () => {ListWrapper.remove(StringMapWrapper.get(el._eventListenersMap, evt), listener);}; } dispatchEvent(el, evt) { - throw _notImplemented('dispatchEvent'); + if (isBlank(evt.target)) { + evt.target = el; + } + if (isPresent(el._eventListenersMap)) { + var listeners = StringMapWrapper.get(el._eventListenersMap, evt.type); + if (isPresent(listeners)) { + for (var i = 0; i < listeners.length; i++) { + listeners[i](evt); + } + } + } + if (isPresent(el.parent)) { + this.dispatchEvent(el.parent, evt); + } + if (isPresent(el._window)) { + this.dispatchEvent(el._window, evt); + } } createMouseEvent(eventType) { - throw _notImplemented('createMouseEvent'); + return this.createEvent(eventType); } createEvent(eventType) { - throw _notImplemented('createEvent'); + return {type: eventType}; } getInnerHTML(el) { return serializer.serialize(this.templateAwareRoot(el)); @@ -378,6 +405,7 @@ export class Parse5DomAdapter extends DomAdapter { this.appendChild(newDoc, body); StringMapWrapper.set(newDoc, "head", head); StringMapWrapper.set(newDoc, "body", body); + StringMapWrapper.set(newDoc, "_window", StringMapWrapper.create()); return newDoc; } defaultDoc() { @@ -482,6 +510,15 @@ export class Parse5DomAdapter extends DomAdapter { supportsNativeShadowDOM(): boolean { return false; } + getGlobalEventTarget(target:string) { + if (target == "window") { + return this.defaultDoc()._window; + } else if (target == "document") { + return this.defaultDoc(); + } else if (target == "body") { + return this.defaultDoc().body; + } + } } //TODO: build a proper list, this one is all the keys of a HTMLInputElement diff --git a/modules/angular2/src/forms/validator_directives.js b/modules/angular2/src/forms/validator_directives.js index e592d65f8d..1d607e8b57 100644 --- a/modules/angular2/src/forms/validator_directives.js +++ b/modules/angular2/src/forms/validator_directives.js @@ -1,6 +1,7 @@ import {Decorator} from 'angular2/angular2'; -import {ControlDirective, Validators} from 'angular2/forms'; +import {Validators} from './validators'; +import {ControlDirective} from './directives'; @Decorator({ selector: '[required]' diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index f60da12e5a..3bac335f5b 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -545,53 +545,53 @@ export function main() { }); })); + it('should support render events', inject([TestBed, AsyncTestCompleter], (tb, async) => { + tb.overrideView(MyComp, new View({ + template: '
', + directives: [DecoratorListeningDomEvent] + })); + + tb.createView(MyComp, {context: ctx}).then((view) => { + + var injector = view.rawView.elementInjectors[0]; + + var listener = injector.get(DecoratorListeningDomEvent); + + dispatchEvent(view.rootNodes[0], 'domEvent'); + + expect(listener.eventType).toEqual('domEvent'); + + async.done(); + }); + })); + + it('should support render global events', inject([TestBed, AsyncTestCompleter], (tb, async) => { + tb.overrideView(MyComp, new View({ + template: '', + directives: [DecoratorListeningDomEvent] + })); + + tb.createView(MyComp, {context: ctx}).then((view) => { + var injector = view.rawView.elementInjectors[0]; + + var listener = injector.get(DecoratorListeningDomEvent); + dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); + expect(listener.eventType).toEqual('window_domEvent'); + + listener = injector.get(DecoratorListeningDomEvent); + dispatchEvent(DOM.getGlobalEventTarget("document"), 'domEvent'); + expect(listener.eventType).toEqual('document_domEvent'); + + view.destroy(); + listener = injector.get(DecoratorListeningDomEvent); + dispatchEvent(DOM.getGlobalEventTarget("body"), 'domEvent'); + expect(listener.eventType).toEqual(''); + + async.done(); + }); + })); + if (DOM.supportsDOMEvents()) { - it('should support render events', inject([TestBed, AsyncTestCompleter], (tb, async) => { - tb.overrideView(MyComp, new View({ - template: '', - directives: [DecoratorListeningDomEvent] - })); - - tb.createView(MyComp, {context: ctx}).then((view) => { - - var injector = view.rawView.elementInjectors[0]; - - var listener = injector.get(DecoratorListeningDomEvent); - - dispatchEvent(view.rootNodes[0], 'domEvent'); - - expect(listener.eventType).toEqual('domEvent'); - - async.done(); - }); - })); - - it('should support render global events', inject([TestBed, AsyncTestCompleter], (tb, async) => { - tb.overrideView(MyComp, new View({ - template: '', - directives: [DecoratorListeningDomEvent] - })); - - tb.createView(MyComp, {context: ctx}).then((view) => { - var injector = view.rawView.elementInjectors[0]; - - var listener = injector.get(DecoratorListeningDomEvent); - dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); - expect(listener.eventType).toEqual('window_domEvent'); - - listener = injector.get(DecoratorListeningDomEvent); - dispatchEvent(DOM.getGlobalEventTarget("document"), 'domEvent'); - expect(listener.eventType).toEqual('document_domEvent'); - - view.destroy(); - listener = injector.get(DecoratorListeningDomEvent); - dispatchEvent(DOM.getGlobalEventTarget("body"), 'domEvent'); - expect(listener.eventType).toEqual(''); - - async.done(); - }); - })); - it('should support preventing default on render events', inject([TestBed, AsyncTestCompleter], (tb, async) => { tb.overrideView(MyComp, new View({ template: '', @@ -608,42 +608,42 @@ export function main() { async.done(); }); })); - - it('should support render global events from multiple directives', inject([TestBed, AsyncTestCompleter], (tb, async) => { - tb.overrideView(MyComp, new View({ - template: '', - directives: [If, DecoratorListeningDomEvent, DecoratorListeningDomEventOther] - })); - - tb.createView(MyComp, {context: ctx}).then((view) => { - globalCounter = 0; - ctx.ctxBoolProp = true; - view.detectChanges(); - - var subview = view.rawView.viewContainers[0].get(0); - var injector = subview.elementInjectors[0]; - var listener = injector.get(DecoratorListeningDomEvent); - var listenerother = injector.get(DecoratorListeningDomEventOther); - dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); - expect(listener.eventType).toEqual('window_domEvent'); - expect(listenerother.eventType).toEqual('other_domEvent'); - expect(globalCounter).toEqual(1); - - ctx.ctxBoolProp = false; - view.detectChanges(); - dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); - expect(globalCounter).toEqual(1); - - ctx.ctxBoolProp = true; - view.detectChanges(); - dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); - expect(globalCounter).toEqual(2); - - async.done(); - }); - })); } + it('should support render global events from multiple directives', inject([TestBed, AsyncTestCompleter], (tb, async) => { + tb.overrideView(MyComp, new View({ + template: '', + directives: [If, DecoratorListeningDomEvent, DecoratorListeningDomEventOther] + })); + + tb.createView(MyComp, {context: ctx}).then((view) => { + globalCounter = 0; + ctx.ctxBoolProp = true; + view.detectChanges(); + + var subview = view.rawView.viewContainers[0].get(0); + var injector = subview.elementInjectors[0]; + var listener = injector.get(DecoratorListeningDomEvent); + var listenerother = injector.get(DecoratorListeningDomEventOther); + dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); + expect(listener.eventType).toEqual('window_domEvent'); + expect(listenerother.eventType).toEqual('other_domEvent'); + expect(globalCounter).toEqual(1); + + ctx.ctxBoolProp = false; + view.detectChanges(); + dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); + expect(globalCounter).toEqual(1); + + ctx.ctxBoolProp = true; + view.detectChanges(); + dispatchEvent(DOM.getGlobalEventTarget("window"), 'domEvent'); + expect(globalCounter).toEqual(2); + + async.done(); + }); + })); + describe('dynamic ViewContainers', () => { it('should allow to create a ViewContainer at any bound location', diff --git a/modules/angular2/test/forms/integration_spec.js b/modules/angular2/test/forms/integration_spec.js index fdfbd15c9c..f84bfb112e 100644 --- a/modules/angular2/test/forms/integration_spec.js +++ b/modules/angular2/test/forms/integration_spec.js @@ -20,27 +20,320 @@ import {Component, Decorator, View, PropertySetter} from 'angular2/angular2'; import {TestBed} from 'angular2/src/test_lib/test_bed'; -import {ControlGroupDirective, ControlDirective, Control, ControlGroup, OptionalControl, - ControlValueAccessor, RequiredValidatorDirective, CheckboxControlValueAccessor, +import {ControlGroupDirective, ControlDirective, Control, ControlGroup, RequiredValidatorDirective, CheckboxControlValueAccessor, DefaultValueAccessor, Validators} from 'angular2/forms'; export function main() { describe("integration tests", () => { - if (DOM.supportsDOMEvents()) { - it("should initialize DOM elements with the given form object", - inject([TestBed, AsyncTestCompleter], (tb, async) => { - var ctx = new MyComp(new ControlGroup({ - "login": new Control("loginValue") - })); + + it("should initialize DOM elements with the given form object", + inject([TestBed, AsyncTestCompleter], (tb, async) => { + var ctx = new MyComp(new ControlGroup({ + "login": new Control("loginValue") + })); + + var t = `