Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Change Detector Unit Tests to run with Pre-generated Change Detectors #2307

Merged
merged 2 commits into from Jun 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -303,6 +303,10 @@ class _CodegenState {
rhs = '$context.${r.name}';
break;

case RECORD_TYPE_SAFE_PROPERTY:
rhs = '${_UTIL}.isValueBlank(${context}) ? null : ${context}.${r.name}';
break;

case RECORD_TYPE_LOCAL:
rhs = '$_LOCALS_ACCESSOR.get("${r.name}")';
break;
Expand All @@ -311,6 +315,11 @@ class _CodegenState {
rhs = '$context.${r.name}($argString)';
break;

case RECORD_TYPE_SAFE_INVOKE_METHOD:
rhs = '${_UTIL}.isValueBlank(${context}) '
'? null : ${context}.${r.name}(${argString})';
break;

case RECORD_TYPE_INVOKE_CLOSURE:
rhs = '$context($argString)';
break;
Expand Down
193 changes: 112 additions & 81 deletions modules/angular2/test/change_detection/change_detector_spec.ts
Expand Up @@ -72,89 +72,165 @@ export function main() {
}
}

function _bindConstValue(expression: string) {
function _bindSimpleValue(expression: string, context = null) {
var dispatcher = new TestDispatcher();
var protoCd = _getProtoChangeDetector(getDefinition(expression, 'propName'));
var cd = protoCd.instantiate(dispatcher);

var context = null;
var locals = null;
cd.hydrate(context, locals, null);
cd.detectChanges();
return dispatcher.log;
}

it('should support literals',
() => { expect(_bindConstValue('10')).toEqual(['propName=10']); });
() => { expect(_bindSimpleValue('10')).toEqual(['propName=10']); });

it('should strip quotes from literals',
() => { expect(_bindConstValue('"str"')).toEqual(['propName=str']); });
() => { expect(_bindSimpleValue('"str"')).toEqual(['propName=str']); });

it('should support newlines in literals',
() => { expect(_bindConstValue('"a\n\nb"')).toEqual(['propName=a\n\nb']); });
() => { expect(_bindSimpleValue('"a\n\nb"')).toEqual(['propName=a\n\nb']); });

it('should support + operations',
() => { expect(_bindConstValue('10 + 2')).toEqual(['propName=12']); });
() => { expect(_bindSimpleValue('10 + 2')).toEqual(['propName=12']); });

it('should support - operations',
() => { expect(_bindConstValue('10 - 2')).toEqual(['propName=8']); });
() => { expect(_bindSimpleValue('10 - 2')).toEqual(['propName=8']); });

it('should support * operations',
() => { expect(_bindConstValue('10 * 2')).toEqual(['propName=20']); });
() => { expect(_bindSimpleValue('10 * 2')).toEqual(['propName=20']); });

it('should support / operations', () => {
expect(_bindConstValue('10 / 2')).toEqual([`propName=${5.0}`]);
expect(_bindSimpleValue('10 / 2')).toEqual([`propName=${5.0}`]);
}); // dart exp=5.0, js exp=5

it('should support % operations',
() => { expect(_bindConstValue('11 % 2')).toEqual(['propName=1']); });
() => { expect(_bindSimpleValue('11 % 2')).toEqual(['propName=1']); });

it('should support == operations on identical',
() => { expect(_bindConstValue('1 == 1')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('1 == 1')).toEqual(['propName=true']); });

it('should support != operations',
() => { expect(_bindConstValue('1 != 1')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('1 != 1')).toEqual(['propName=false']); });

it('should support == operations on coerceible', () => {
var expectedValue = IS_DARTIUM ? 'false' : 'true';
expect(_bindConstValue('1 == true')).toEqual([`propName=${expectedValue}`]);
expect(_bindSimpleValue('1 == true')).toEqual([`propName=${expectedValue}`]);
});

it('should support === operations on identical',
() => { expect(_bindConstValue('1 === 1')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('1 === 1')).toEqual(['propName=true']); });

it('should support !== operations',
() => { expect(_bindConstValue('1 !== 1')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('1 !== 1')).toEqual(['propName=false']); });

it('should support === operations on coerceible',
() => { expect(_bindConstValue('1 === true')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('1 === true')).toEqual(['propName=false']); });

it('should support true < operations',
() => { expect(_bindConstValue('1 < 2')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('1 < 2')).toEqual(['propName=true']); });

it('should support false < operations',
() => { expect(_bindConstValue('2 < 1')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('2 < 1')).toEqual(['propName=false']); });

it('should support false > operations',
() => { expect(_bindConstValue('1 > 2')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('1 > 2')).toEqual(['propName=false']); });

it('should support true > operations',
() => { expect(_bindConstValue('2 > 1')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('2 > 1')).toEqual(['propName=true']); });

it('should support true <= operations',
() => { expect(_bindConstValue('1 <= 2')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('1 <= 2')).toEqual(['propName=true']); });

it('should support equal <= operations',
() => { expect(_bindConstValue('2 <= 2')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('2 <= 2')).toEqual(['propName=true']); });

it('should support false <= operations',
() => { expect(_bindConstValue('2 <= 1')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('2 <= 1')).toEqual(['propName=false']); });

it('should support true >= operations',
() => { expect(_bindConstValue('2 >= 1')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('2 >= 1')).toEqual(['propName=true']); });

it('should support equal >= operations',
() => { expect(_bindConstValue('2 >= 2')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('2 >= 2')).toEqual(['propName=true']); });

it('should support false >= operations',
() => { expect(_bindConstValue('1 >= 2')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('1 >= 2')).toEqual(['propName=false']); });

it('should support true && operations',
() => { expect(_bindConstValue('true && true')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('true && true')).toEqual(['propName=true']); });

it('should support false && operations',
() => { expect(_bindConstValue('true && false')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('true && false')).toEqual(['propName=false']); });

it('should support true || operations',
() => { expect(_bindConstValue('true || false')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('true || false')).toEqual(['propName=true']); });

it('should support false || operations',
() => { expect(_bindConstValue('false || false')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('false || false')).toEqual(['propName=false']); });

it('should support negate',
() => { expect(_bindConstValue('!true')).toEqual(['propName=false']); });
() => { expect(_bindSimpleValue('!true')).toEqual(['propName=false']); });

it('should support double negate',
() => { expect(_bindConstValue('!!true')).toEqual(['propName=true']); });
() => { expect(_bindSimpleValue('!!true')).toEqual(['propName=true']); });

it('should support true conditionals',
() => { expect(_bindConstValue('1 < 2 ? 1 : 2')).toEqual(['propName=1']); });
() => { expect(_bindSimpleValue('1 < 2 ? 1 : 2')).toEqual(['propName=1']); });

it('should support false conditionals',
() => { expect(_bindConstValue('1 > 2 ? 1 : 2')).toEqual(['propName=2']); });
() => { expect(_bindSimpleValue('1 > 2 ? 1 : 2')).toEqual(['propName=2']); });

it('should support keyed access to a list item',
() => { expect(_bindConstValue('["foo", "bar"][0]')).toEqual(['propName=foo']); });
() => { expect(_bindSimpleValue('["foo", "bar"][0]')).toEqual(['propName=foo']); });

it('should support keyed access to a map item',
() => { expect(_bindConstValue('{"foo": "bar"}["foo"]')).toEqual(['propName=bar']); });
() => { expect(_bindSimpleValue('{"foo": "bar"}["foo"]')).toEqual(['propName=bar']); });

it('should report all changes on the first run including uninitialized values', () => {
expect(_bindSimpleValue('value', new Uninitialized())).toEqual(['propName=null']);
});

it('should report all changes on the first run including null values', () => {
var td = new TestData(null);
expect(_bindSimpleValue('a', td)).toEqual(['propName=null']);
});

it('should support simple chained property access', () => {
var address = new Address('Grenoble');
var person = new Person('Victor', address);

expect(_bindSimpleValue('address.city', person)).toEqual(['propName=Grenoble']);
});

it('should support the safe navigation operator', () => {
var person = new Person('Victor', null);

expect(_bindSimpleValue('address?.city', person)).toEqual(['propName=null']);
expect(_bindSimpleValue('address?.toString()', person)).toEqual(['propName=null']);

person.address = new Address('MTV');

expect(_bindSimpleValue('address?.city', person)).toEqual(['propName=MTV']);
expect(_bindSimpleValue('address?.toString()', person)).toEqual(['propName=MTV']);
});

it("should support method calls", () => {
var person = new Person('Victor');
expect(_bindSimpleValue('sayHi("Jim")', person)).toEqual(['propName=Hi, Jim']);
});

it("should support function calls", () => {
var td = new TestData(() => (a) => a);
expect(_bindSimpleValue('a()(99)', td)).toEqual(['propName=99']);
});

it("should support chained method calls", () => {
var person = new Person('Victor');
var td = new TestData(person);
expect(_bindSimpleValue('a.sayHi("Jim")', td)).toEqual(['propName=Hi, Jim']);
});
});
});

Expand Down Expand Up @@ -248,51 +324,6 @@ export function main() {
expect(dispatcher.log).toEqual(['name=Misko']);
});

it('should report all changes on the first run including uninitialized values', () => {
expect(executeWatch('value', 'value', new Uninitialized())).toEqual(['value=null']);
});

it('should report all changes on the first run including null values', () => {
var td = new TestData(null);
expect(executeWatch('a', 'a', td)).toEqual(['a=null']);
});

it('should support simple chained property access', () => {
var address = new Address('Grenoble');
var person = new Person('Victor', address);

expect(executeWatch('address.city', 'address.city', person))
.toEqual(['address.city=Grenoble']);
});

it('should support the safe navigation operator', () => {
var person = new Person('Victor', null);

expect(executeWatch('city', 'address?.city', person)).toEqual(['city=null']);
expect(executeWatch('city', 'address?.toString()', person)).toEqual(['city=null']);

person.address = new Address('MTV');

expect(executeWatch('city', 'address?.city', person)).toEqual(['city=MTV']);
expect(executeWatch('city', 'address?.toString()', person)).toEqual(['city=MTV']);
});

it("should support method calls", () => {
var person = new Person('Victor');
expect(executeWatch('m', 'sayHi("Jim")', person)).toEqual(['m=Hi, Jim']);
});

it("should support function calls", () => {
var td = new TestData(() => (a) => a);
expect(executeWatch('value', 'a()(99)', td)).toEqual(['value=99']);
});

it("should support chained method calls", () => {
var person = new Person('Victor');
var td = new TestData(person);
expect(executeWatch('m', 'a.sayHi("Jim")', td)).toEqual(['m=Hi, Jim']);
});

it("should support literal array", () => {
var c = createChangeDetector('array', '[1,2]');
c["changeDetector"].detectChanges();
Expand Down
13 changes: 12 additions & 1 deletion modules/angular2/test/change_detection/simple_watch_config.ts
@@ -1,10 +1,13 @@
import {ListWrapper} from 'angular2/src/facade/collection';
import {BindingRecord, ChangeDetectorDefinition, Lexer, Parser} from 'angular2/change_detection';
import {reflector} from 'angular2/src/reflection/reflection';
import {ReflectionCapabilities} from 'angular2/src/reflection/reflection_capabilities';

var _parser = new Parser(new Lexer());

function _createChangeDetectorDefinition(id: string, propName: string,
expression: string): ChangeDetectorDefinition {
reflector.reflectionCapabilities = new ReflectionCapabilities();
var ast = _parser.parseBinding(expression, 'location');
var bindingRecords = [BindingRecord.createForElement(ast, 0, propName)];

Expand Down Expand Up @@ -68,5 +71,13 @@ var _availableDefinitions = [
'1 < 2 ? 1 : 2',
'1 > 2 ? 1 : 2',
'["foo", "bar"][0]',
'{"foo": "bar"}["foo"]'
'{"foo": "bar"}["foo"]',
'value',
'a',
'address.city',
'address?.city',
'address?.toString()',
'sayHi("Jim")',
'a()(99)',
'a.sayHi("Jim")'
];