320 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			320 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
 | 
						|
import {isBlank, isPresent} from 'angular2/src/facade/lang';
 | 
						|
import {
 | 
						|
  DEFAULT,
 | 
						|
  ON_PUSH,
 | 
						|
  BindingRecord,
 | 
						|
  ChangeDetectorDefinition,
 | 
						|
  DirectiveIndex,
 | 
						|
  DirectiveRecord,
 | 
						|
  Lexer,
 | 
						|
  Locals,
 | 
						|
  Parser
 | 
						|
} from 'angular2/src/change_detection/change_detection';
 | 
						|
import {reflector} from 'angular2/src/reflection/reflection';
 | 
						|
import {ReflectionCapabilities} from 'angular2/src/reflection/reflection_capabilities';
 | 
						|
 | 
						|
/*
 | 
						|
 * This file defines `ChangeDetectorDefinition` objects which are used in the tests defined in
 | 
						|
 * the change_detector_spec library. Please see that library for more information.
 | 
						|
 */
 | 
						|
 | 
						|
var _parser = new Parser(new Lexer());
 | 
						|
 | 
						|
function _getParser() {
 | 
						|
  reflector.reflectionCapabilities = new ReflectionCapabilities();
 | 
						|
  return _parser;
 | 
						|
}
 | 
						|
 | 
						|
function _createBindingRecords(expression: string): List<BindingRecord> {
 | 
						|
  var ast = _getParser().parseBinding(expression, 'location');
 | 
						|
  return [BindingRecord.createForElementProperty(ast, 0, PROP_NAME)];
 | 
						|
}
 | 
						|
 | 
						|
function _convertLocalsToVariableBindings(locals: Locals): List<any> {
 | 
						|
  var variableBindings = [];
 | 
						|
  var loc = locals;
 | 
						|
  while (isPresent(loc) && isPresent(loc.current)) {
 | 
						|
    MapWrapper.forEach(loc.current, (v, k) => variableBindings.push(k));
 | 
						|
    loc = loc.parent;
 | 
						|
  }
 | 
						|
  return variableBindings;
 | 
						|
}
 | 
						|
 | 
						|
export var PROP_NAME = 'propName';
 | 
						|
 | 
						|
/**
 | 
						|
 * In this case, we expect `id` and `expression` to be the same string.
 | 
						|
 */
 | 
						|
export function getDefinition(id: string): TestDefinition {
 | 
						|
  var testDef = null;
 | 
						|
  if (StringMapWrapper.contains(_ExpressionWithLocals.availableDefinitions, id)) {
 | 
						|
    let val = StringMapWrapper.get(_ExpressionWithLocals.availableDefinitions, id);
 | 
						|
    let cdDef = val.createChangeDetectorDefinition();
 | 
						|
    cdDef.id = id;
 | 
						|
    testDef = new TestDefinition(id, cdDef, val.locals);
 | 
						|
  } else if (StringMapWrapper.contains(_ExpressionWithMode.availableDefinitions, id)) {
 | 
						|
    let val = StringMapWrapper.get(_ExpressionWithMode.availableDefinitions, id);
 | 
						|
    let cdDef = val.createChangeDetectorDefinition();
 | 
						|
    cdDef.id = id;
 | 
						|
    testDef = new TestDefinition(id, cdDef, null);
 | 
						|
  } else if (StringMapWrapper.contains(_DirectiveUpdating.availableDefinitions, id)) {
 | 
						|
    let val = StringMapWrapper.get(_DirectiveUpdating.availableDefinitions, id);
 | 
						|
    let cdDef = val.createChangeDetectorDefinition();
 | 
						|
    cdDef.id = id;
 | 
						|
    testDef = new TestDefinition(id, cdDef, null);
 | 
						|
  } else if (ListWrapper.indexOf(_availableDefinitions, id) >= 0) {
 | 
						|
    var strategy = null;
 | 
						|
    var variableBindings = [];
 | 
						|
    var bindingRecords = _createBindingRecords(id);
 | 
						|
    var directiveRecords = [];
 | 
						|
    let cdDef = new ChangeDetectorDefinition(id, strategy, variableBindings, bindingRecords,
 | 
						|
                                             directiveRecords, true);
 | 
						|
    testDef = new TestDefinition(id, cdDef, null);
 | 
						|
  }
 | 
						|
  if (isBlank(testDef)) {
 | 
						|
    throw `No ChangeDetectorDefinition for ${id} available. Please modify this file if necessary.`;
 | 
						|
  }
 | 
						|
 | 
						|
  return testDef;
 | 
						|
}
 | 
						|
 | 
						|
export class TestDefinition {
 | 
						|
  constructor(public id: string, public cdDef: ChangeDetectorDefinition, public locals: Locals) {}
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Get all available ChangeDetectorDefinition objects. Used to pre-generate Dart
 | 
						|
 * `ChangeDetector` classes.
 | 
						|
 */
 | 
						|
export function getAllDefinitions(): List<TestDefinition> {
 | 
						|
  var allDefs = _availableDefinitions;
 | 
						|
  allDefs = ListWrapper.concat(allDefs,
 | 
						|
                               StringMapWrapper.keys(_ExpressionWithLocals.availableDefinitions));
 | 
						|
  allDefs =
 | 
						|
      ListWrapper.concat(allDefs, StringMapWrapper.keys(_ExpressionWithMode.availableDefinitions));
 | 
						|
  allDefs =
 | 
						|
      ListWrapper.concat(allDefs, StringMapWrapper.keys(_DirectiveUpdating.availableDefinitions));
 | 
						|
  return ListWrapper.map(allDefs, (id) => getDefinition(id));
 | 
						|
}
 | 
						|
 | 
						|
class _ExpressionWithLocals {
 | 
						|
  constructor(private _expression: string, public locals: Locals) {}
 | 
						|
 | 
						|
  createChangeDetectorDefinition(): ChangeDetectorDefinition {
 | 
						|
    var strategy = null;
 | 
						|
    var variableBindings = _convertLocalsToVariableBindings(this.locals);
 | 
						|
    var bindingRecords = _createBindingRecords(this._expression);
 | 
						|
    var directiveRecords = [];
 | 
						|
    return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings, bindingRecords,
 | 
						|
                                        directiveRecords, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Map from test id to _ExpressionWithLocals.
 | 
						|
   * Tests in this map define an expression and local values which those expressions refer to.
 | 
						|
   */
 | 
						|
  static availableDefinitions: StringMap<string, _ExpressionWithLocals> = {
 | 
						|
    'valueFromLocals': new _ExpressionWithLocals(
 | 
						|
        'key', new Locals(null, MapWrapper.createFromPairs([['key', 'value']]))),
 | 
						|
    'functionFromLocals': new _ExpressionWithLocals(
 | 
						|
        'key()', new Locals(null, MapWrapper.createFromPairs([['key', () => 'value']]))),
 | 
						|
    'nestedLocals': new _ExpressionWithLocals(
 | 
						|
        'key',
 | 
						|
        new Locals(new Locals(null, MapWrapper.createFromPairs([['key', 'value']])), new Map())),
 | 
						|
    'fallbackLocals': new _ExpressionWithLocals(
 | 
						|
        'name', new Locals(null, MapWrapper.createFromPairs([['key', 'value']]))),
 | 
						|
    'contextNestedPropertyWithLocals': new _ExpressionWithLocals(
 | 
						|
        'address.city', new Locals(null, MapWrapper.createFromPairs([['city', 'MTV']]))),
 | 
						|
    'localPropertyWithSimilarContext': new _ExpressionWithLocals(
 | 
						|
        'city', new Locals(null, MapWrapper.createFromPairs([['city', 'MTV']])))
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
class _ExpressionWithMode {
 | 
						|
  constructor(private _strategy: string, private _withRecords: boolean) {}
 | 
						|
 | 
						|
  createChangeDetectorDefinition(): ChangeDetectorDefinition {
 | 
						|
    var variableBindings = [];
 | 
						|
    var bindingRecords = null;
 | 
						|
    var directiveRecords = null;
 | 
						|
    if (this._withRecords) {
 | 
						|
      var dirRecordWithOnPush =
 | 
						|
          new DirectiveRecord({directiveIndex: new DirectiveIndex(0, 0), changeDetection: ON_PUSH});
 | 
						|
      var updateDirWithOnPushRecord =
 | 
						|
          BindingRecord.createForDirective(_getParser().parseBinding('42', 'location'), 'a',
 | 
						|
                                           (o, v) => (<any>o).a = v, dirRecordWithOnPush);
 | 
						|
      bindingRecords = [updateDirWithOnPushRecord];
 | 
						|
      directiveRecords = [dirRecordWithOnPush];
 | 
						|
    } else {
 | 
						|
      bindingRecords = [];
 | 
						|
      directiveRecords = [];
 | 
						|
    }
 | 
						|
    return new ChangeDetectorDefinition('(empty id)', this._strategy, variableBindings,
 | 
						|
                                        bindingRecords, directiveRecords, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Map from test id to _ExpressionWithMode.
 | 
						|
   * Definitions in this map define conditions which allow testing various change detector modes.
 | 
						|
   */
 | 
						|
  static availableDefinitions: StringMap<string, _ExpressionWithMode> = {
 | 
						|
    'emptyUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, false),
 | 
						|
    'emptyUsingOnPushStrategy': new _ExpressionWithMode(ON_PUSH, false),
 | 
						|
    'onPushRecordsUsingDefaultStrategy': new _ExpressionWithMode(DEFAULT, true)
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
class _DirectiveUpdating {
 | 
						|
  constructor(private _bindingRecords: List<BindingRecord>,
 | 
						|
              private _directiveRecords: List<DirectiveRecord>) {}
 | 
						|
 | 
						|
  createChangeDetectorDefinition(): ChangeDetectorDefinition {
 | 
						|
    var strategy = null;
 | 
						|
    var variableBindings = [];
 | 
						|
 | 
						|
    return new ChangeDetectorDefinition('(empty id)', strategy, variableBindings,
 | 
						|
                                        this._bindingRecords, this._directiveRecords, true);
 | 
						|
  }
 | 
						|
 | 
						|
  static updateA(expression: string, dirRecord): BindingRecord {
 | 
						|
    return BindingRecord.createForDirective(_getParser().parseBinding(expression, 'location'), 'a',
 | 
						|
                                            (o, v) => (<any>o).a = v, dirRecord);
 | 
						|
  }
 | 
						|
 | 
						|
  static updateB(expression: string, dirRecord): BindingRecord {
 | 
						|
    return BindingRecord.createForDirective(_getParser().parseBinding(expression, 'location'), 'b',
 | 
						|
                                            (o, v) => (<any>o).b = v, dirRecord);
 | 
						|
  }
 | 
						|
 | 
						|
  static basicRecords: List<DirectiveRecord> = [
 | 
						|
    new DirectiveRecord({
 | 
						|
      directiveIndex: new DirectiveIndex(0, 0),
 | 
						|
      callOnChange: true,
 | 
						|
      callOnCheck: true,
 | 
						|
      callOnAllChangesDone: true
 | 
						|
    }),
 | 
						|
    new DirectiveRecord({
 | 
						|
      directiveIndex: new DirectiveIndex(0, 1),
 | 
						|
      callOnChange: true,
 | 
						|
      callOnCheck: true,
 | 
						|
      callOnAllChangesDone: true
 | 
						|
    })
 | 
						|
  ];
 | 
						|
 | 
						|
  static recordNoCallbacks = new DirectiveRecord({
 | 
						|
    directiveIndex: new DirectiveIndex(0, 0),
 | 
						|
    callOnChange: false,
 | 
						|
    callOnCheck: false,
 | 
						|
    callOnAllChangesDone: false
 | 
						|
  });
 | 
						|
 | 
						|
  /**
 | 
						|
   * Map from test id to _DirectiveUpdating.
 | 
						|
   * Definitions in this map define definitions which allow testing directive updating.
 | 
						|
   */
 | 
						|
  static availableDefinitions:
 | 
						|
      StringMap<string, _DirectiveUpdating> = {
 | 
						|
        'directNoDispatcher': new _DirectiveUpdating(
 | 
						|
            [_DirectiveUpdating.updateA('42', _DirectiveUpdating.basicRecords[0])],
 | 
						|
            [_DirectiveUpdating.basicRecords[0]]),
 | 
						|
        'groupChanges':
 | 
						|
            new _DirectiveUpdating(
 | 
						|
                [
 | 
						|
                  _DirectiveUpdating.updateA('1', _DirectiveUpdating.basicRecords[0]),
 | 
						|
                  _DirectiveUpdating.updateB('2', _DirectiveUpdating.basicRecords[0]),
 | 
						|
                  BindingRecord.createDirectiveOnChange(_DirectiveUpdating.basicRecords[0]),
 | 
						|
                  _DirectiveUpdating.updateA('3', _DirectiveUpdating.basicRecords[1]),
 | 
						|
                  BindingRecord.createDirectiveOnChange(_DirectiveUpdating.basicRecords[1])
 | 
						|
                ],
 | 
						|
                [_DirectiveUpdating.basicRecords[0], _DirectiveUpdating.basicRecords[1]]),
 | 
						|
        'directiveOnCheck': new _DirectiveUpdating(
 | 
						|
            [BindingRecord.createDirectiveOnCheck(_DirectiveUpdating.basicRecords[0])],
 | 
						|
            [_DirectiveUpdating.basicRecords[0]]),
 | 
						|
        'directiveOnInit': new _DirectiveUpdating(
 | 
						|
            [BindingRecord.createDirectiveOnInit(_DirectiveUpdating.basicRecords[0])],
 | 
						|
            [_DirectiveUpdating.basicRecords[0]]),
 | 
						|
        'emptyWithDirectiveRecords': new _DirectiveUpdating(
 | 
						|
            [], [_DirectiveUpdating.basicRecords[0], _DirectiveUpdating.basicRecords[1]]),
 | 
						|
        'noCallbacks': new _DirectiveUpdating(
 | 
						|
            [_DirectiveUpdating.updateA('1', _DirectiveUpdating.recordNoCallbacks)],
 | 
						|
            [_DirectiveUpdating.recordNoCallbacks]),
 | 
						|
        'readingDirectives':
 | 
						|
            new _DirectiveUpdating(
 | 
						|
                [
 | 
						|
                  BindingRecord.createForHostProperty(new DirectiveIndex(0, 0),
 | 
						|
                                                      _getParser().parseBinding('a', 'location'),
 | 
						|
                                                      PROP_NAME)
 | 
						|
                ],
 | 
						|
                [_DirectiveUpdating.basicRecords[0]]),
 | 
						|
        'interpolation':
 | 
						|
            new _DirectiveUpdating(
 | 
						|
                [
 | 
						|
                  BindingRecord.createForElementProperty(
 | 
						|
                      _getParser().parseInterpolation('B{{a}}A', 'location'), 0, PROP_NAME)
 | 
						|
                ],
 | 
						|
                [])
 | 
						|
      };
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * The list of all test definitions this config supplies.
 | 
						|
 * Items in this list that do not appear in other structures define tests with expressions
 | 
						|
 * equivalent to their ids.
 | 
						|
 */
 | 
						|
var _availableDefinitions = [
 | 
						|
  '"$"',
 | 
						|
  '10',
 | 
						|
  '"str"',
 | 
						|
  '"a\n\nb"',
 | 
						|
  '10 + 2',
 | 
						|
  '10 - 2',
 | 
						|
  '10 * 2',
 | 
						|
  '10 / 2',
 | 
						|
  '11 % 2',
 | 
						|
  '1 == 1',
 | 
						|
  '1 != 1',
 | 
						|
  '1 == true',
 | 
						|
  '1 === 1',
 | 
						|
  '1 !== 1',
 | 
						|
  '1 === true',
 | 
						|
  '1 < 2',
 | 
						|
  '2 < 1',
 | 
						|
  '1 > 2',
 | 
						|
  '2 > 1',
 | 
						|
  '1 <= 2',
 | 
						|
  '2 <= 2',
 | 
						|
  '2 <= 1',
 | 
						|
  '2 >= 1',
 | 
						|
  '2 >= 2',
 | 
						|
  '1 >= 2',
 | 
						|
  'true && true',
 | 
						|
  'true && false',
 | 
						|
  'true || false',
 | 
						|
  'false || false',
 | 
						|
  '!true',
 | 
						|
  '!!true',
 | 
						|
  '1 < 2 ? 1 : 2',
 | 
						|
  '1 > 2 ? 1 : 2',
 | 
						|
  '["foo", "bar"][0]',
 | 
						|
  '{"foo": "bar"}["foo"]',
 | 
						|
  'name',
 | 
						|
  '[1, 2]',
 | 
						|
  '[1, a]',
 | 
						|
  '{z: 1}',
 | 
						|
  '{z: a}',
 | 
						|
  'name | pipe',
 | 
						|
  '(name | pipe).length',
 | 
						|
  "name | pipe:'one':address.city",
 | 
						|
  'value',
 | 
						|
  'a',
 | 
						|
  'address.city',
 | 
						|
  'address?.city',
 | 
						|
  'address?.toString()',
 | 
						|
  'sayHi("Jim")',
 | 
						|
  'a()(99)',
 | 
						|
  'a.sayHi("Jim")',
 | 
						|
  'passThrough([12])',
 | 
						|
  'invalidFn(1)'
 | 
						|
];
 |