diff --git a/modules/change_detection/src/record.js b/modules/change_detection/src/record.js index 1b52d14499..fff5e451af 100644 --- a/modules/change_detection/src/record.js +++ b/modules/change_detection/src/record.js @@ -95,25 +95,26 @@ export class Record { this.funcOrValue = null; this.args = null; - if (protoRecord.recordType === PROTO_RECORD_CONST) { + var type = protoRecord.recordType; + if (type === PROTO_RECORD_CONST) { this.mode = MODE_STATE_CONST; this.funcOrValue = protoRecord.funcOrValue; - } else if (protoRecord.recordType === PROTO_RECORD_PURE_FUNCTION) { + } else if (type === PROTO_RECORD_PURE_FUNCTION) { this.mode = MODE_STATE_INVOKE_PURE_FUNCTION; this.funcOrValue = protoRecord.funcOrValue; this.args = ListWrapper.createFixedSize(protoRecord.arity); - } else if (protoRecord.recordType === PROTO_RECORD_METHOD) { + } else if (type === PROTO_RECORD_METHOD) { this.mode = MODE_STATE_INVOKE_METHOD; this.funcOrValue = protoRecord.funcOrValue; this.args = ListWrapper.createFixedSize(protoRecord.arity); - } else if (protoRecord.recordType === PROTO_RECORD_CLOSURE) { + } else if (type === PROTO_RECORD_CLOSURE) { this.mode = MODE_STATE_INVOKE_CLOSURE; this.args = ListWrapper.createFixedSize(protoRecord.arity); - } else if (protoRecord.recordType === PROTO_RECORD_PROPERTY) { + } else if (type === PROTO_RECORD_PROPERTY) { this.mode = MODE_STATE_PROPERTY; this.funcOrValue = protoRecord.funcOrValue; } @@ -210,7 +211,6 @@ const MODE_STATE_LIST = 0x0006; const MODE_STATE_CONST = 0x0007; function isSame(a, b) { - if (a instanceof String && b instanceof String) return a == b; if (a === b) return true; if ((a !== a) && (b !== b)) return true; return false; diff --git a/modules/change_detection/src/watch_group.js b/modules/change_detection/src/watch_group.js index 54ae35eae7..fc484f43c4 100644 --- a/modules/change_detection/src/watch_group.js +++ b/modules/change_detection/src/watch_group.js @@ -9,7 +9,7 @@ import {AST, AccessMember, ImplicitReceiver, AstVisitor, LiteralPrimitive, export class ProtoWatchGroup { @FIELD('headRecord:ProtoRecord') @FIELD('tailRecord:ProtoRecord') - constructor(formatters) { + constructor(formatters=null) { this.formatters = formatters; this.headRecord = null; @@ -154,17 +154,6 @@ class ProtoRecordCreator { //do nothing } - // TODO: add tests for this method! - visitLiteralPrimitive(ast:LiteralPrimitive) { - // do nothing - } - - // TODO: add tests for this method! - visitBinary(ast:Binary) { - ast.left.visit(this); - ast.right.visit(this); - } - visitLiteralPrimitive(ast:LiteralPrimitive, dest) { this.add(this.construct(PROTO_RECORD_CONST, ast.value, 0, dest)); } diff --git a/modules/core/test/compiler/view_spec.js b/modules/core/test/compiler/view_spec.js index 1151ca7d3a..32cab0b94d 100644 --- a/modules/core/test/compiler/view_spec.js +++ b/modules/core/test/compiler/view_spec.js @@ -21,133 +21,81 @@ export function main() { describe('ProtoView.instantiate', function() { - function createCollectDomNodesTestCases(useTemplateElement:boolean) { + describe('collect root nodes', () => { - function templateAwareCreateElement(html) { - return createElement(useTemplateElement ? `` : html); - } - - it('should collect the root node in the ProtoView element', () => { - var pv = new ProtoView(templateAwareCreateElement('
'), new ProtoWatchGroup()); + it('should use the ProtoView element if it is no TemplateElement', () => { + var pv = new ProtoView(createElement('
'), new ProtoWatchGroup(null)); var view = pv.instantiate(null, null); expect(view.nodes.length).toBe(1); expect(view.nodes[0].getAttribute('id')).toEqual('1'); }); - describe('collect elements with property bindings', () => { - - it('should collect property bindings on the root element if it has the ng-binding class', () => { - var pv = new ProtoView(templateAwareCreateElement('
'), new ProtoWatchGroup()); - pv.bindElement(null); - pv.bindElementProperty('prop', parser.parseBinding('a')); - - var view = pv.instantiate(null, null); - expect(view.bindElements.length).toEqual(1); - expect(view.bindElements[0]).toBe(view.nodes[0]); - }); - - it('should collect property bindings on child elements with ng-binding class', () => { - var pv = new ProtoView(templateAwareCreateElement('
'), - new ProtoWatchGroup()); - pv.bindElement(null); - pv.bindElementProperty('a', parser.parseBinding('b')); - - var view = pv.instantiate(null, null); - expect(view.bindElements.length).toEqual(1); - expect(view.bindElements[0]).toBe(view.nodes[0].childNodes[1]); - }); - + it('should use the ProtoView elements children if it is a TemplateElement', () => { + var pv = new ProtoView(createElement(''), + new ProtoWatchGroup()); + var view = pv.instantiate(null, null); + expect(view.nodes.length).toBe(1); + expect(view.nodes[0].getAttribute('id')).toEqual('1'); }); - describe('collect text nodes with bindings', () => { - - it('should collect text nodes under the root element', () => { - var pv = new ProtoView(templateAwareCreateElement('
{{}}{{}}
'), new ProtoWatchGroup()); - pv.bindElement(null); - pv.bindTextNode(0, parser.parseBinding('a')); - pv.bindTextNode(2, parser.parseBinding('b')); - - var view = pv.instantiate(null, null); - expect(view.textNodes.length).toEqual(2); - expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[0]); - expect(view.textNodes[1]).toBe(view.nodes[0].childNodes[2]); - }); - - it('should collect text nodes with bindings on child elements with ng-binding class', () => { - var pv = new ProtoView(templateAwareCreateElement('
{{}}
'), - new ProtoWatchGroup()); - pv.bindElement(null); - pv.bindTextNode(0, parser.parseBinding('b')); - - var view = pv.instantiate(null, null); - expect(view.textNodes.length).toEqual(1); - expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[1].childNodes[0]); - }); - - }); - } - - describe('collect dom nodes with a regular element as root', () => { - createCollectDomNodesTestCases(false); }); - describe('collect dom nodes with a template element as root', () => { - createCollectDomNodesTestCases(true); + describe('collect elements with property bindings', () => { + + it('should collect property bindings on the root element if it has the ng-binding class', () => { + var pv = new ProtoView(createElement('
'), new ProtoWatchGroup(null)); + pv.bindElement(null); + pv.bindElementProperty('prop', parser.parseBinding('a')); + + var view = pv.instantiate(null, null); + expect(view.bindElements.length).toEqual(1); + expect(view.bindElements[0]).toBe(view.nodes[0]); + }); + + it('should collect property bindings on child elements with ng-binding class', () => { + var pv = new ProtoView(createElement('
'), + new ProtoWatchGroup(null)); + pv.bindElement(null); + pv.bindElementProperty('a', parser.parseBinding('b')); + + var view = pv.instantiate(null, null); + expect(view.bindElements.length).toEqual(1); + expect(view.bindElements[0]).toBe(view.nodes[0].childNodes[1]); + }); + + }); + + describe('collect text nodes with bindings', () => { + + it('should collect text nodes under the root element', () => { + var pv = new ProtoView(createElement('
{{}}{{}}
'), new ProtoWatchGroup(null)); + pv.bindElement(null); + pv.bindTextNode(0, parser.parseBinding('a')); + pv.bindTextNode(2, parser.parseBinding('b')); + + var view = pv.instantiate(null, null); + expect(view.textNodes.length).toEqual(2); + expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[0]); + expect(view.textNodes[1]).toBe(view.nodes[0].childNodes[2]); + }); + + it('should collect text nodes with bindings on child elements with ng-binding class', () => { + var pv = new ProtoView(createElement('
{{}}
'), + new ProtoWatchGroup(null)); + pv.bindElement(null); + pv.bindTextNode(0, parser.parseBinding('b')); + + var view = pv.instantiate(null, null); + expect(view.textNodes.length).toEqual(1); + expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[1].childNodes[0]); + }); + }); describe('react to watch group changes', function() { - var view; - beforeEach(() => { - var template = DOM.createTemplate(tempalteWithThreeTypesOfBindings); - var pv = new ProtoView(template, templateElementBinders(), - new ProtoWatchGroup(null), false); - view = pv.instantiate(null, null); - }); - - it('should consume text node changes', () => { - var record = new Record(null, null); - record.currentValue = 'Hello World!'; - view.onRecordChange(record , 0); - expect(view.textNodes[0].nodeValue).toEqual('Hello World!'); - }); - }); - - it('should consume element binding changes', () => { - var elementWithBinding = view.bindElements[0]; - expect(elementWithBinding.id).toEqual(''); - var record = new Record(null, null); - var memento = new ElementPropertyMemento(0, 'id'); - record.currentValue = 'foo'; - view.onRecordChange(record, memento); - expect(elementWithBinding.id).toEqual('foo'); - }); - - it('should collect multiple root element injectors', () => { - var pv = new ProtoView(createElement('
'), - new ProtoWatchGroup()); - pv.bindElement(new ProtoElementInjector(null, 1, [Directive])); - pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective])); - - expect(elInj.get(Directive).prop).toEqual('foo'); - var record = new Record(null, null); - var memento = new DirectivePropertyMemento(1, 0, 'prop', - (o, v) => o.prop = v); - record.currentValue = 'bar'; - view.onRecordChange(record, memento); - expect(elInj.get(Directive).prop).toEqual('bar'); - }); - - }); - - describe('react to watch group changes', () => { - var view, cd, ctx; - - var protoWatchGroup = new ProtoWatchGroup(); - protoWatchGroup.watch(oneFieldAst('foo'), memento); - - var pv = new ProtoView(template, templateElementBinders(), - protoWatchGroup, false); + var ctx, view, cd; + function createView(protoView) { ctx = new MyEvaluationContext(); view = protoView.instantiate(ctx, null); cd = new ChangeDetector(view.watchGroup); @@ -190,6 +138,51 @@ export function main() { }); }); + describe('react to watch group changes', () => { + var view, cd, ctx; + + function createView(protoView) { + ctx = new MyEvaluationContext(); + view = protoView.instantiate(ctx, null); + cd = new ChangeDetector(view.watchGroup); + } + + it('should consume text node changes', () => { + var pv = new ProtoView(createElement('
{{}}
'), + new ProtoWatchGroup(null)); + pv.bindElement(null); + pv.bindTextNode(0, parser.parseBinding('foo')); + createView(pv); + + ctx.foo = 'buz'; + cd.detectChanges(); + expect(view.textNodes[0].nodeValue).toEqual('buz'); + }); + + it('should consume element binding changes', () => { + var pv = new ProtoView(createElement('
'), + new ProtoWatchGroup(null)); + pv.bindElement(null); + pv.bindElementProperty('id', parser.parseBinding('foo')); + createView(pv); + + ctx.foo = 'buz'; + cd.detectChanges(); + expect(view.bindElements[0].id).toEqual('buz'); + }); + + it('should consume directive watch expression change.', () => { + var pv = new ProtoView(createElement('
'), + new ProtoWatchGroup(null)); + pv.bindElement(new ProtoElementInjector(null, 0, [Directive])); + pv.bindDirectiveProperty( 0, parser.parseBinding('foo'), 'prop', closureMap.setter('prop')); + createView(pv); + + ctx.foo = 'buz'; + cd.detectChanges(); + expect(view.elementInjectors[0].get(Directive).prop).toEqual('buz'); + }); + }); }); }); }