diff --git a/lib/introspection.dart b/lib/introspection.dart index f130c9397..9fa900b91 100644 --- a/lib/introspection.dart +++ b/lib/introspection.dart @@ -64,23 +64,38 @@ List _findAllProbesInTree(dom.Node node) { * * The node parameter could be: * * a [dom.Node], - * * a CSS selector for this node. + * * a CSS selector to look for a matching node inside the [root] or the dom.document. + * + * Specifying a [root] element allows querying a node that is not attached to the DOM. It is an + * error to pass a [root] element that is already attached to the DOM. * * **NOTE:** This global method is here to make it easier to debug Angular * application from the browser's REPL, unit or end-to-end tests. The * function is not intended to be called from Angular application. */ -ElementProbe ngProbe(nodeOrSelector) { - if (nodeOrSelector == null) throw "ngProbe called without node"; +ElementProbe ngProbe(nodeOrSelector, [dom.Node root]) { + if (nodeOrSelector == null) throw "ngProbe called without node/selector"; var node = nodeOrSelector; if (nodeOrSelector is String) { - var nodes = ngQuery(dom.document, nodeOrSelector); - node = (nodes.isNotEmpty) ? nodes.first : null; + if (root == null) { + root = dom.document; + } else { + var attached = false; + for (var parent = root.parentNode; parent != null; parent = parent.parentNode) { + if (parent == dom.document) { + attached = true; + break; + } + } + if (attached) throw "The root element must not be attached to the DOM"; + root = new dom.DivElement()..append(root); + } + var nodes = ngQuery(root, nodeOrSelector); + if (nodes.isEmpty) throw "The '$nodeOrSelector' selector does not match any node"; + node = nodes.first; } var probe = _findProbeWalkingUp(node); - if (probe != null) { - return probe; - } + if (probe != null) return probe; var forWhat = (nodeOrSelector is String) ? "selector" : "node"; throw "Could not find a probe for the $forWhat '$nodeOrSelector' nor its parents"; } @@ -93,7 +108,8 @@ ElementProbe ngProbe(nodeOrSelector) { * application from the browser's REPL, unit or end-to-end tests. The function * is not intended to be called from Angular application. */ -DirectiveInjector ngInjector(nodeOrSelector) => ngProbe(nodeOrSelector).injector; +DirectiveInjector ngInjector(nodeOrSelector, [dom.Node root]) => + ngProbe(nodeOrSelector, root).injector; /** @@ -103,17 +119,16 @@ DirectiveInjector ngInjector(nodeOrSelector) => ngProbe(nodeOrSelector).injector * application from the browser's REPL, unit or end-to-end tests. The function * is not intended to be called from Angular application. */ -Scope ngScope(nodeOrSelector) => ngProbe(nodeOrSelector).scope; +Scope ngScope(nodeOrSelector, [dom.Node root]) => ngProbe(nodeOrSelector, root).scope; -List ngQuery(dom.Node element, String selector, - [String containsText]) { +List ngQuery(dom.Node element, String selector, [String containsText]) { var list = []; var children = [element]; if ((element is dom.Element) && element.shadowRoot != null) { children.add(element.shadowRoot); } - while (!children.isEmpty) { + while (children.isNotEmpty) { var child = children.removeAt(0); child.querySelectorAll(selector).forEach((e) { if (containsText == null || e.text.contains(containsText)) list.add(e); @@ -136,7 +151,6 @@ List ngQuery(dom.Node element, String selector, List ngDirectives(nodeOrSelector) => ngProbe(nodeOrSelector).directives; - js.JsObject _jsProbe(ElementProbe probe) { return _jsify({ "element": probe.element, @@ -217,7 +231,7 @@ _jsify(var obj) { return _jsFunction(obj); } if ((obj is Map) || (obj is Iterable)) { - var mappedObj = (obj is Map) ? + var mappedObj = (obj is Map) ? new Map.fromIterables(obj.keys, obj.values.map(_jsify)) : obj.map(_jsify); if (obj is List) { return new js.JsArray.from(mappedObj); diff --git a/lib/mock/test_bed.dart b/lib/mock/test_bed.dart index d1c54da81..a996be1e4 100644 --- a/lib/mock/test_bed.dart +++ b/lib/mock/test_bed.dart @@ -31,7 +31,7 @@ class TestBed { * - [List] then treat it as a collection of nods * * After the compilation the [rootElements] contains an array of compiled root nodes, - * and [rootElement] contains the first element from the [rootElemets]. + * and [rootElement] contains the first element from the [rootElements]. * * An option [scope] parameter can be supplied to link it with non root scope. */ @@ -46,7 +46,7 @@ class TestBed { } else { throw 'Expecting: String, Node, or List got $html.'; } - rootElement = rootElements.length > 0 && rootElements[0] is Element ? rootElements[0] : null; + rootElement = rootElements.isNotEmpty && rootElements[0] is Element ? rootElements[0] : null; if (directives == null) { directives = injector.getByKey(DIRECTIVE_MAP_KEY); } diff --git a/test/core_dom/compiler_spec.dart b/test/core_dom/compiler_spec.dart index abf996847..f227c8b0e 100644 --- a/test/core_dom/compiler_spec.dart +++ b/test/core_dom/compiler_spec.dart @@ -4,8 +4,11 @@ import '../_specs.dart'; import 'package:angular/core_dom/directive_injector.dart'; -forBothCompilers(fn) { +var probeEnabled; + +forCompilerSetups(fn) { describe('walking compiler', () { + probeEnabled = true; beforeEachModule((Module m) { m.bind(Compiler, toImplementation: WalkingCompiler); return m; @@ -14,6 +17,7 @@ forBothCompilers(fn) { }); describe('tagging compiler', () { + probeEnabled = true; beforeEachModule((Module m) { m.bind(Compiler, toImplementation: TaggingCompiler); return m; @@ -22,6 +26,7 @@ forBothCompilers(fn) { }); describe('tagging compiler with ElementProbe disabled', () { + probeEnabled = false; beforeEachModule((Module m) { m.bind(Compiler, toImplementation: TaggingCompiler); m.bind(CompilerConfig, toValue: new CompilerConfig.withOptions(elementProbeEnabled: false)); @@ -32,7 +37,9 @@ forBothCompilers(fn) { } forAllCompilersAndComponentFactories(fn) { - forBothCompilers(fn); + describe('shadow dom components', () { + forCompilerSetups(fn); + }); describe('transcluding components', () { beforeEachModule((Module m) { @@ -46,7 +53,7 @@ forAllCompilersAndComponentFactories(fn) { } void main() { - forBothCompilers((compilerType) => + forCompilerSetups((compilerType) => describe('TranscludingComponentFactory', () { TestBed _; @@ -370,7 +377,7 @@ void main() { })); it('should store ElementProbe with Elements', async(() { - if (compilerType == 'tagging-no-elementProbe') return; + if (!probeEnabled) return; _.compile('
innerText
'); microLeap(); @@ -632,9 +639,8 @@ void main() { }); it('should expose PublishModuleDirectiveSuperType as PublishModuleDirectiveSuperType', () { - _.compile(r'
'); - Probe probe = _.rootScope.context['publishModuleProbe']; - var directive = probe.injector.get(PublishModuleDirectiveSuperType); + _.compile(r'
'); + var directive = PublishModuleAttrDirective._injector.get(PublishModuleDirectiveSuperType); expect(directive is PublishModuleAttrDirective).toBeTruthy(); }); diff --git a/test/core_dom/selector_spec.dart b/test/core_dom/selector_spec.dart index 524359a4c..95bb7fecd 100644 --- a/test/core_dom/selector_spec.dart +++ b/test/core_dom/selector_spec.dart @@ -2,7 +2,7 @@ library angular.dom.selector_spec; import '../_specs.dart'; -const _aBElement = const Decorator(selector:'b'); +const _aBElement = const Decorator(selector:'b'); const _aBClass = const Decorator(selector:'.b'); const _aDirectiveAttr = const Decorator(selector:'[directive]'); const _aWildcardDirectiveAttr = const Decorator(selector:'[wildcard-*]'); @@ -181,10 +181,9 @@ main() { it('should match ng-model + required on the same element', () { expect( - selector(element = e('')), + selector(element = e('')), toEqualsDirectiveInfos([ { "selector": '[ng-model]', "value": 'val', "element": element}, - { "selector": '[probe]', "value": 'i', "element": element}, { "selector": '[ng-model][required]', "value": 'true', "element": element}, { "selector": 'input[type=text][ng-model]', "value": 'val', "element": element} ])); diff --git a/test/core_dom/view_spec.dart b/test/core_dom/view_spec.dart index 3be620b3e..78e66a5a5 100644 --- a/test/core_dom/view_spec.dart +++ b/test/core_dom/view_spec.dart @@ -218,7 +218,8 @@ main() { Compiler compiler = rootInjector.get(Compiler); DirectiveMap directives = rootInjector.get(DirectiveMap); - compiler(es('{{\'a\' | formatterA}}'), directives)(rootScope, rootInjector.get(DirectiveInjector)); + var els = es('{{\'a\' | formatterA}}'); + compiler(els, directives)(rootScope, rootInjector.get(DirectiveInjector)); rootScope.apply(); expect(log.log, equals(['AFormatter', 'ADirective'])); @@ -232,11 +233,12 @@ main() { DirectiveMap newDirectives = childInjector.get(DirectiveMap); var scope = childInjector.get(Scope); - compiler(es('{{\'a\' | formatterA}}' - '{{\'b\' | formatterB}}'), newDirectives)(scope, childInjector.get(DirectiveInjector)); + els = es('{{\'a\' | formatterA}}{{\'b\' | formatterB}}'); + compiler(els, newDirectives)(scope, childInjector.get(DirectiveInjector)); rootScope.apply(); - expect(log.log, equals(['AFormatter', 'ADirective', 'BFormatter', 'ADirective', 'BDirective'])); + expect(log.log) + .toEqual(['AFormatter', 'ADirective', 'BFormatter', 'ADirective', 'BDirective']); }); }); diff --git a/test/directive/ng_form_spec.dart b/test/directive/ng_form_spec.dart index a0cb7624e..b06b3b785 100644 --- a/test/directive/ng_form_spec.dart +++ b/test/directive/ng_form_spec.dart @@ -21,14 +21,14 @@ void main() { it('should return the first control with the given name when accessed using map notation', (Scope scope, TestBed _) { _.compile('
' - ' ' - ' ' + ' ' + ' ' '
'); scope.apply(); NgForm form = _.rootScope.context['myForm']; - NgModel one = _.rootScope.context['a'].directive(NgModel); - NgModel two = _.rootScope.context['b'].directive(NgModel); + NgModel one = ngInjector('input:nth-child(1)', _.rootElement).get(NgModel); + NgModel two = ngInjector('input:nth-child(2)', _.rootElement).get(NgModel); expect(one).not.toBe(two); expect(form['model']).toBe(one); @@ -37,14 +37,14 @@ void main() { it('should return the all the controls with the given name', (Scope scope, TestBed _) { _.compile('
' - ' ' - ' ' + ' ' + ' ' '
'); scope.apply(); NgForm form = _.rootScope.context['myForm']; - NgModel one = _.rootScope.context['a'].directive(NgModel); - NgModel two = _.rootScope.context['b'].directive(NgModel); + NgModel one = ngInjector('input:nth-child(1)', _.rootElement).get(NgModel); + NgModel two = ngInjector('input:nth-child(2)', _.rootElement).get(NgModel); expect(one).not.toBe(two); @@ -67,25 +67,24 @@ void main() { }); it('should add and remove the correct CSS classes when set to dirty and to pristine', (Scope scope, TestBed _) { - var element = e('
'); + var element = e('
'); _.compile(element); scope.apply(); - Probe probe = _.rootScope.context['m']; - var input = probe.directive(NgModel); + var model = ngInjector('input', element).get(NgModel); var form = scope.context['myForm']; - input.addInfo('ng-dirty'); - input.validate(); + model.addInfo('ng-dirty'); + model.validate(); scope.apply(); expect(form).not.toBePristine(); expect(element).not.toHaveClass('ng-pristine'); expect(element).toHaveClass('ng-dirty'); - input.removeInfo('ng-dirty'); - input.validate(); + model.removeInfo('ng-dirty'); + model.validate(); scope.apply(); expect(form).toBePristine(); @@ -96,14 +95,14 @@ void main() { it('should revert back to pristine on the form if the value is reset on the model', (Scope scope, TestBed _) { _.compile('
' + - ' ' + - ' ' + + ' ' + + ' ' + '
'); scope.apply(); var form = scope.context['myForm']; - var model1 = scope.context['m'].directive(NgModel); - var model2 = scope.context['n'].directive(NgModel); + var model1 = ngInjector('input:nth-child(1)', _.rootElement).get(NgModel); + var model2 = ngInjector('input:nth-child(2)', _.rootElement).get(NgModel); expect(model1).toBePristine(); expect(model2).toBePristine(); @@ -144,21 +143,20 @@ void main() { }); it('should expose NgForm as NgControl', (Scope scope, TestBed _) { - _.compile('
'); + var form = _.compile('
'); scope.apply(); - expect(scope.context['formProbe'].injector.get(NgControl) is NgForm).toBeTruthy(); + expect(ngInjector(form).get(NgControl) is NgForm).toBeTruthy(); }); it('should add and remove the correct flags when set to valid and to invalid', (Scope scope, TestBed _) { - var element = e('
'); + var element = e('
'); _.compile(element); scope.apply(); - Probe probe = _.rootScope.context['m']; - var model = probe.directive(NgModel); + var model = ngInjector('input', _.rootElement).get(NgModel); var form = scope.context['myForm']; model.addError('some-error'); @@ -282,8 +280,8 @@ void main() { it('should register the name of inner forms that contain the ng-form attribute', (Scope scope, TestBed _) { _.compile('
' - '
' - ' ' + '
' + ' ' '
' ''); scope.apply(() { @@ -291,24 +289,23 @@ void main() { }); var form = scope.context['myForm']; - var inner = _.rootScope.context['f'].directive(NgForm); + var inner = ngInjector('[ng-form="myInnerForm"]', _.rootElement).get(NgForm); expect(inner.name).toEqual('myInnerForm'); - expect(scope.eval('myForm["myInnerForm"]["one"].viewValue')) - .toEqual('it works!'); + expect(scope.eval('myForm["myInnerForm"]["one"].viewValue')).toEqual('it works!'); }); it('should set the validity for the parent form when fieldsets are used', (Scope scope, TestBed _) { _.compile('
' - '
' - ' ' + '
' + ' ' '
' ''); scope.apply(); var form = scope.context['myForm']; - var fieldset = _.rootScope.context['f'].directive(NgForm); - var model = _.rootScope.context['m'].directive(NgModel); + var fieldset = ngInjector('fieldset', _.rootElement).get(NgForm); + var model = ngInjector('input', _.rootElement).get(NgModel); model.addError("error"); @@ -465,14 +462,13 @@ void main() { (TestBed _, Scope scope) { _.compile('
' - ' ' + ' ' '
'); scope.apply(); NgForm form = _.rootScope.context['superForm']; - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); var formElement = form.element.node; + var model = ngInjector('input', _.rootElement).get(NgModel); expect(form.submitted).toBe(false); expect(form.validSubmit).toBe(false); @@ -556,12 +552,12 @@ void main() { scope.context['required'] = true; _.compile('
' - '' + ' ' '
'); scope.apply(); var form = scope.context['myForm']; - var model = scope.context['i'].directive(NgModel); + var model = ngInjector('input', _.rootElement).get(NgModel); expect(form).not.toBeValid(); expect(model).not.toBeValid(); @@ -602,14 +598,12 @@ void main() { describe('reset()', () { it('should reset the model value to its original state', (TestBed _) { _.compile('
' + - ' ' + ' ' '
'); _.rootScope.apply('myModel = "animal"'); NgForm form = _.rootScope.context['superForm']; - - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + var model = ngInjector('input', _.rootElement).get(NgModel); expect(_.rootScope.context['myModel']).toEqual('animal'); expect(model.modelValue).toEqual('animal'); @@ -634,9 +628,9 @@ void main() { (TestBed _, Scope scope) { var form = _.compile('
' - ' ' + ' ' '
'); - var model = _.rootScope.context['i'].directive(NgModel); + var model = ngInjector('input', _.rootElement).get(NgModel); var input = model.element.node; NgForm formModel = _.rootScope.context['duperForm']; @@ -670,11 +664,11 @@ void main() { it('should reset each of the controls to be untouched only when the form has a valid submission', (Scope scope, TestBed _) { var form = _.compile('
' - ' ' + ' ' '
'); NgForm formModel = _.rootScope.context['duperForm']; - var model = _.rootScope.context['i'].directive(NgModel); + var model = ngInjector('input', _.rootElement).get(NgModel); var input = model.element.node; _.triggerEvent(input, 'blur'); @@ -703,12 +697,11 @@ void main() { s.context['name'] = 'cool'; var form = _.compile('
' - ' ' + ' ' '
'); NgForm formModel = s.context['myForm']; - Probe probe = s.context['i']; - var model = probe.directive(NgModel); + var model = ngInjector('input', _.rootElement).get(NgModel); expect(s.eval('name')).toEqual('cool'); expect(s.eval('myForm.name')).toEqual('myForm'); diff --git a/test/directive/ng_model_select_spec.dart b/test/directive/ng_model_select_spec.dart index 9ef64fbe1..7f620f60f 100644 --- a/test/directive/ng_model_select_spec.dart +++ b/test/directive/ng_model_select_spec.dart @@ -13,7 +13,7 @@ main() { it('should retrieve using ng-value', () { _.compile( - '' '' ''); var r2d2 = {"name":"r2d2"}; @@ -31,7 +31,7 @@ main() { it('should retrieve using ng-value', () { _.compile( - '' '' ''); var r2d2 = { "name":"r2d2"}; @@ -84,7 +84,7 @@ main() { it('should work with repeated value options', () { _.compile( - '' '' ''); @@ -92,7 +92,7 @@ main() { _.rootScope.context['robot'] = 'r2d2'; _.rootScope.apply(); - var select = _.rootScope.context['p'].directive(InputSelect); + var select = ngInjector('option', _.rootElement).get(InputSelect); expect(_.rootElement).toEqualSelect(['c3p0', ['r2d2']]); _.rootElement.querySelectorAll('option')[0].selected = true; @@ -145,14 +145,14 @@ main() { it('should set the model to empty string when empty option is selected', () { _.rootScope.context['robot'] = 'x'; _.compile( - '' + '' + '' + '' ''); _.rootScope.apply(); - var select = _.rootScope.context['p'].directive(InputSelect); + var select = ngInjector('select', _.rootElement).get(InputSelect); expect(_.rootElement).toEqualSelect(['', ['x'], 'y']); @@ -166,9 +166,9 @@ main() { it('should select empty option when model is undefined', () { _.rootScope.context['robots'] = ['c3p0', 'r2d2']; _.compile( - '' + '' + '' ''); _.rootScope.apply(); expect(_.rootElement).toEqualSelect([[''], 'c3p0', 'r2d2']); @@ -177,12 +177,12 @@ main() { it('should set model to empty string when selected', () { _.rootScope.context['robots'] = ['c3p0', 'r2d2']; _.compile( - '' + '' + '' ''); _.rootScope.apply(); - var select = _.rootScope.context['p'].directive(InputSelect); + var select = ngInjector('select', _.rootElement).get(InputSelect); _.selectOption(_.rootElement, 'c3p0'); expect(_.rootElement).toEqualSelect(['', ['c3p0'], 'r2d2']); @@ -499,13 +499,11 @@ main() { it('should require', () { compile( - '' + '' + '' + ''); - var element = scope.context['i'].element; - scope.context['log'] = ''; scope.context['change'] = () { scope.context['log'] += 'change;'; @@ -623,12 +621,11 @@ main() { it('should require', () { compile( - '' + '' + '' ''); - var element = scope.context['i'].element; scope.apply(() { scope.context['selection'] = []; }); @@ -867,7 +864,7 @@ main() { it('should bind to scope value and group', () { var element = _.compile( - '' '' '' diff --git a/test/directive/ng_model_spec.dart b/test/directive/ng_model_spec.dart index b952f9408..940a05cc5 100644 --- a/test/directive/ng_model_spec.dart +++ b/test/directive/ng_model_spec.dart @@ -72,17 +72,15 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector('input', _.rootElement); - inputElement.value = 'abc'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = 'abc'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual('abc'); - inputElement.value = 'def'; - var input = probe.directive(InputTextLike); + inputEl.value = 'def'; + var input = injector.get(InputTextLike); input.processValue(); expect(_.rootScope.context['model']).toEqual('def'); }); @@ -128,64 +126,53 @@ void main() { }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var ngModel = ngInjector(inputEl).get(NgModel); ngModel.render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); describe('type="number" or type="range"', () { it('should update model from the input value for type=number', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - inputElement.value = '12'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = '12'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual(12); - inputElement.value = '14'; - var input = probe.directive(InputNumberLike); + inputEl.value = '14'; + var input = injector.get(InputNumberLike); input.processValue(); expect(_.rootScope.context['model']).toEqual(14); }); it('should update input type=number to blank when model is null', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); - inputElement.value = '12'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = '12'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual(12); _.rootScope.context['model'] = null; _.rootScope.apply(); - expect(inputElement.value).toEqual(''); + expect(inputEl.value).toEqual(''); }); it('should be invalid when the input value results in a NaN value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; - - inputElement.value = 'aa'; - _.triggerEvent(inputElement, 'change'); + var inputEl = _.compile(''); + inputEl.value = 'aa'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model'].isNaN).toBe(true); + var injector = ngInjector(inputEl); + var ngModel = injector.get(NgModel); expect(ngModel.valid).toBe(false); }); @@ -250,81 +237,67 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - inputElement.value = '42'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = '42'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual(42); - inputElement.value = '43'; - var input = probe.directive(InputNumberLike); + inputEl.value = '43'; + var input = injector.get(InputNumberLike); input.processValue(); expect(_.rootScope.context['model']).toEqual(43); }); it('should update model to NaN from a blank input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; - - inputElement.value = ''; - _.triggerEvent(inputElement, 'change'); + _.compile(''); + InputElement inputEl = _.rootElement; + inputEl.value = ''; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model'].isNaN).toBeTruthy(); }); it('should update model from the input value for range inputs', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - inputElement.value = '42'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = '42'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual(42); - inputElement.value = '43'; - var input = probe.directive(InputNumberLike); + inputEl.value = '43'; + var input = injector.get(InputNumberLike); input.processValue(); expect(_.rootScope.context['model']).toEqual(43); }); it('should update model to a native default value from a blank range input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; - - inputElement.value = ''; - _.triggerEvent(inputElement, 'change'); + _.compile(''); + InputElement inputEl = _.rootElement; + inputEl.value = ''; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toBeDefined(); }); it('should render null as blank', () { _.compile(''); - _.rootScope.apply(); - _.rootScope.apply('model = null'); expect((_.rootElement as dom.InputElement).value).toEqual(''); }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - ngModel.render(123); + injector.get(NgModel).render(123); scope.context['model'] = 123; - - expect(inputElement.value).not.toEqual('123'); + expect(inputEl.value).not.toEqual('123'); scope.apply(); - - expect(inputElement.value).toEqual('123'); + expect(inputEl.value).toEqual('123'); }); }); @@ -351,24 +324,22 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - inputElement.value = 'abc'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = 'abc'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual('abc'); - inputElement.value = 'def'; - var input = probe.directive(InputTextLike); + inputEl.value = 'def'; + var input = injector.get(InputTextLike); input.processValue(); expect(_.rootScope.context['model']).toEqual('def'); }); - it('should write to input only if value is different', - (Injector i, Animate animate) { + it('should write to input only if value is different', (Injector i, Animate animate) { NodeAttrs nodeAttrs = new NodeAttrs(new DivElement()); @@ -406,19 +377,16 @@ void main() { }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); @@ -444,17 +412,16 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - inputElement.value = 'abc'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = 'abc'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual('abc'); - inputElement.value = 'def'; - var input = probe.directive(InputTextLike); + inputEl.value = 'def'; + var input = injector.get(InputTextLike); input.processValue(); expect(_.rootScope.context['model']).toEqual('def'); }); @@ -500,19 +467,16 @@ void main() { }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); @@ -549,23 +513,20 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); + - inputElement.value = 'abc'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = 'abc'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual('abc'); - inputElement.value = 'def'; - var input = probe.directive(InputTextLike); - input.processValue(); + inputEl.value = 'def'; + var input = injector.get(InputTextLike); expect(_.rootScope.context['model']).toEqual('def'); }); - it('should write to input only if value is different', - (Injector i, Animate animate) { + it('should write to input only if value is different', (Injector i, Animate animate) { NodeAttrs nodeAttrs = new NodeAttrs(new DivElement()); @@ -603,19 +564,15 @@ void main() { }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + InputElement inputEl = probe.element; ngModel.render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); @@ -635,9 +592,9 @@ void main() { }); it('should render as dirty when checked', (Scope scope) { - var element = _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + var element = _.compile(''); + var injector = ngInjector(element); + var model = injector.get(NgModel); expect(model.pristine).toEqual(true); expect(model.dirty).toEqual(false); @@ -719,19 +676,15 @@ void main() { }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = true; - - expect(inputElement.checked).toBe(false); + expect(inputEl.checked).toBe(false); scope.apply(); - - expect(inputElement.checked).toBe(true); + expect(inputEl.checked).toBe(true); }); }); @@ -757,17 +710,15 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - TextAreaElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); describe('type="radio"', () { it('should update input value from model', () { - _.compile('' + - '' + - ''); + _.compile('
' + '' + '' + '' + '
'); _.rootScope.apply(); - RadioButtonInputElement redBtn = _.rootScope.context['r'].element; - RadioButtonInputElement greenBtn = _.rootScope.context['g'].element; - RadioButtonInputElement blueBtn = _.rootScope.context['b'].element; + var inputs = ngQuery(_.rootElement, 'input'); + + RadioButtonInputElement redBtn = inputs[0]; + RadioButtonInputElement greenBtn = inputs[1]; + RadioButtonInputElement blueBtn = inputs[2]; expect(redBtn.checked).toBe(false); expect(greenBtn.checked).toBe(false); @@ -873,9 +824,11 @@ void main() { }); it('should support ng-value', () { - _.compile('' + - '' + - ''); + _.compile('
' + '' + '' + '' + '
'); var red = {'name': 'RED'}; var green = {'name': 'GREEN'}; @@ -887,9 +840,11 @@ void main() { _.rootScope.apply(); - RadioButtonInputElement redBtn = _.rootScope.context['r'].element; - RadioButtonInputElement greenBtn = _.rootScope.context['g'].element; - RadioButtonInputElement blueBtn = _.rootScope.context['b'].element; + var inputs = ngQuery(_.rootElement, 'input'); + + RadioButtonInputElement redBtn = inputs[0]; + RadioButtonInputElement greenBtn = inputs[1]; + RadioButtonInputElement blueBtn = inputs[2]; expect(redBtn.checked).toBe(false); expect(greenBtn.checked).toBe(false); @@ -928,14 +883,13 @@ void main() { it('should render as dirty when checked', (Scope scope) { var element = _.compile( - '
' + - ' ' + - ' ' + + '
' + ' ' + ' ' '
' ); - Probe probe = _.rootScope.context['i']; - - var model = probe.directive(NgModel); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); var input1 = element.querySelector("#on"); var input2 = element.querySelector("#off"); @@ -945,10 +899,10 @@ void main() { expect(model.pristine).toEqual(true); expect(model.dirty).toEqual(false); - expect(input1.classes.contains("ng-dirty")).toBe(false); - expect(input2.classes.contains("ng-dirty")).toBe(false); - expect(input1.classes.contains("ng-pristine")).toBe(true); - expect(input1.classes.contains("ng-pristine")).toBe(true); + expect(input1).not.toHaveClass("ng-dirty"); + expect(input2).not.toHaveClass("ng-dirty"); + expect(input1).toHaveClass("ng-pristine"); + expect(input2).toHaveClass("ng-pristine"); input1.checked = true; _.triggerEvent(input1, 'click'); @@ -962,38 +916,35 @@ void main() { _.triggerEvent(input2, 'click'); scope.apply(); - expect(input1.classes.contains("ng-dirty")).toBe(true); - expect(input2.classes.contains("ng-dirty")).toBe(true); - expect(input1.classes.contains("ng-pristine")).toBe(false); - expect(input1.classes.contains("ng-pristine")).toBe(false); + expect(input1).toHaveClass("ng-dirty"); + expect(input2).toHaveClass("ng-dirty"); + expect(input1).not.toHaveClass("ng-pristine"); + expect(input2).not.toHaveClass("ng-pristine"); }); it('should only render the input value upon the next digest', (Scope scope) { var element = _.compile( - '
' + - ' ' + - ' ' + + '
' + ' ' + ' ' '
' ); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); - Probe probe1 = _.rootScope.context['i']; - var ngModel1 = probe1.directive(NgModel); - InputElement inputElement1 = probe1.element; - - Probe probe2 = _.rootScope.context['j']; - var ngModel2 = probe2.directive(NgModel); - InputElement inputElement2 = probe2.element; + var input1 = element.querySelector("#on"); + var input2 = element.querySelector("#off"); - ngModel1.render('on'); + model.render('on'); scope.context['model'] = 'on'; - expect(inputElement1.checked).toBe(false); - expect(inputElement2.checked).toBe(false); + expect(input1.checked).toBe(false); + expect(input2.checked).toBe(false); scope.apply(); - expect(inputElement1.checked).toBe(true); - expect(inputElement2.checked).toBe(false); + expect(input1.checked).toBe(true); + expect(input2.checked).toBe(false); }); }); @@ -1019,35 +970,29 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - inputElement.value = 'xzy'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = 'xzy'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual('xzy'); - inputElement.value = '123'; - var input = probe.directive(InputTextLike); + inputEl.value = '123'; + var input = injector.get(InputTextLike); input.processValue(); expect(_.rootScope.context['model']).toEqual('123'); }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); @@ -1073,35 +1018,30 @@ void main() { }); it('should update model from the input value', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + _.compile(''); + var injector = ngInjector('input', _.rootElement); + InputElement inputEl = _.rootElement; - inputElement.value = 'xzy'; - _.triggerEvent(inputElement, 'change'); + inputEl.value = 'xzy'; + _.triggerEvent(inputEl, 'change'); expect(_.rootScope.context['model']).toEqual('xzy'); - inputElement.value = '123'; - var input = probe.directive(InputTextLike); + inputEl.value = '123'; + var input = injector.get(InputTextLike); input.processValue(); expect(_.rootScope.context['model']).toEqual('123'); }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - InputElement inputElement = probe.element; + var inputEl = _.compile(''); + var injector = ngInjector(inputEl); - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = 'xyz'; - - expect(inputElement.value).not.toEqual('xyz'); + expect(inputEl.value).not.toEqual('xyz'); scope.apply(); - - expect(inputElement.value).toEqual('xyz'); + expect(inputEl.value).toEqual('xyz'); }); }); @@ -1110,15 +1050,14 @@ void main() { _.compile('

'); _.rootScope.apply(); - expect(_.rootElement.text).toEqual(''); + expect(_.rootElement).toHaveText(''); _.rootScope.apply('model = "misko"'); - expect(_.rootElement.text).toEqual('misko'); + expect(_.rootElement).toHaveText('misko'); }); it('should update model from the input value', () { - _.compile('

'); - Element element = _.rootElement; + var element = _.compile('

'); element.innerHtml = 'abc'; _.triggerEvent(element, 'change'); @@ -1131,37 +1070,32 @@ void main() { }); it('should only render the input value upon the next digest', (Scope scope) { - _.compile('

'); - Probe probe = _.rootScope.context['p']; - var ngModel = probe.directive(NgModel); - Element element = probe.element; + Element element = _.compile('
'); + var injector = ngInjector(element); - ngModel.render('xyz'); + injector.get(NgModel).render('xyz'); scope.context['model'] = 'xyz'; - - expect(element.innerHtml).not.toEqual('xyz'); + expect(element).not.toHaveText('xyz'); scope.apply(); - - expect(element.innerHtml).toEqual('xyz'); + expect(element).toHaveText('xyz'); }); }); describe('pristine / dirty', () { it('should be set to pristine by default', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); expect(model.pristine).toEqual(true); expect(model.dirty).toEqual(false); }); it('should add and remove the correct CSS classes when set to dirty and to pristine', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - NgModel model = probe.directive(NgModel); - InputElement element = probe.element; + var element = _.compile(''); + var injector = ngInjector(element); + NgModel model = injector.get(NgModel); model.addInfo('ng-dirty'); scope.apply(); @@ -1184,17 +1118,19 @@ void main() { it('should render the parent form/fieldset as dirty but not the other models', (Scope scope) { - _.compile('
' + - '
' + - ' ' + - ' ' + - '
' + + _.compile('' + '
' + ' ' + ' ' + '
' '
'); + var inputs = ngQuery(_.rootElement, 'input'); + var formElement = _.rootScope.context['myForm'].element.node; var fieldsetElement = _.rootScope.context['myFieldset'].element.node; - var inputElement1 = _.rootScope.context['myModel1'].element; - var inputElement2 = _.rootScope.context['myModel2'].element; + var inputEl1 = inputs[0]; + var inputEl2 = inputs[1]; scope.apply(); @@ -1204,14 +1140,14 @@ void main() { expect(fieldsetElement).toHaveClass('ng-pristine'); expect(fieldsetElement).not.toHaveClass('ng-dirty'); - expect(inputElement1).toHaveClass('ng-pristine'); - expect(inputElement1).not.toHaveClass('ng-dirty'); + expect(inputEl1).toHaveClass('ng-pristine'); + expect(inputEl1).not.toHaveClass('ng-dirty'); - expect(inputElement2).toHaveClass('ng-pristine'); - expect(inputElement2).not.toHaveClass('ng-dirty'); + expect(inputEl2).toHaveClass('ng-pristine'); + expect(inputEl2).not.toHaveClass('ng-dirty'); - inputElement1.value = '...hi...'; - _.triggerEvent(inputElement1, 'change'); + inputEl1.value = '...hi...'; + _.triggerEvent(inputEl1, 'change'); scope.apply(); expect(formElement).not.toHaveClass('ng-pristine'); @@ -1220,21 +1156,21 @@ void main() { expect(fieldsetElement).not.toHaveClass('ng-pristine'); expect(fieldsetElement).toHaveClass('ng-dirty'); - expect(inputElement1).not.toHaveClass('ng-pristine'); - expect(inputElement1).toHaveClass('ng-dirty'); + expect(inputEl1).not.toHaveClass('ng-pristine'); + expect(inputEl1).toHaveClass('ng-dirty'); - expect(inputElement2).toHaveClass('ng-pristine'); - expect(inputElement2).not.toHaveClass('ng-dirty'); + expect(inputEl2).toHaveClass('ng-pristine'); + expect(inputEl2).not.toHaveClass('ng-dirty'); }); }); describe('validation', () { it('should happen automatically when the scope changes', (Scope scope) { - _.compile(''); + _.compile(''); _.rootScope.apply(); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); expect(model.invalid).toBe(true); expect(model.valid).toBe(false); @@ -1246,18 +1182,17 @@ void main() { }); it('should happen automatically upon user input via the onInput event', () { - _.compile(''); + var inputEl = _.compile(''); _.rootScope.apply(); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); - InputElement inputElement = model.element.node; + var injector = ngInjector(inputEl); + var model = injector.get(NgModel); expect(model.invalid).toBe(true); expect(model.valid).toBe(false); - inputElement.value = 'some value'; - _.triggerEvent(inputElement, 'input'); + inputEl.value = 'some value'; + _.triggerEvent(inputEl, 'input'); expect(model.invalid).toBe(false); expect(model.valid).toBe(true); @@ -1266,10 +1201,9 @@ void main() { describe('valid / invalid', () { it('should add and remove the correct flags when set to valid and to invalid', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); - InputElement element = probe.element; + var element = _.compile(''); + var injector = ngInjector(element); + var model = injector.get(NgModel); model.addError('ng-required'); model.validate(); @@ -1291,9 +1225,9 @@ void main() { }); it('should set the validity with respect to all existing validations when setValidity() is used', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); model.addError("required"); expect(model.valid).toEqual(false); @@ -1313,9 +1247,9 @@ void main() { }); it('should register each error only once when invalid', (Scope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); model.addError("distinct-error"); expect(model.valid).toEqual(false); @@ -1335,36 +1269,28 @@ void main() { it('should return true or false depending on if an error exists on a form', (Scope scope, TestBed _) { - _.compile(''); + _.compile(''); scope.apply(); - Probe p = scope.context['i']; - NgModel model = p.directive(NgModel); - + var injector = ngInjector('input', _.rootElement); + NgModel model = injector.get(NgModel); expect(model.hasErrorState('big-failure')).toBe(false); model.addError("big-failure"); - expect(model.hasErrorState('big-failure')).toBe(true); model.removeError("big-failure"); - expect(model.hasErrorState('big-failure')).toBe(false); }); }); describe('text-like events', () { it('should update the binding on the "input" event', () { - _.compile(''); - Probe probe = _.rootScope.context['p']; - InputElement inputElement = probe.element; - - inputElement.value = 'waaaah'; - + var inputEl = _.compile(''); + inputEl.value = 'waaaah'; expect(_.rootScope.context['model']).not.toEqual('waaaah'); - _.triggerEvent(inputElement, 'input'); - + _.triggerEvent(inputEl, 'input'); expect(_.rootScope.context['model']).toEqual('waaaah'); }); }); @@ -1372,12 +1298,11 @@ void main() { describe('error messages', () { it('should produce a useful error for bad ng-model expressions', () { expect(async(() { - _.compile('
'); + _.compile(''); _.rootScope.apply('myModel = "animal"'); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); expect(_.rootScope.context['myModel']).toEqual('animal'); expect(model.modelValue).toEqual('animal'); @@ -1411,8 +1336,9 @@ void main() { }); it('should set the model to be untouched when the model is reset', () { - var input = _.compile(''); - var model = _.rootScope.context['i'].directive(NgModel); + var input = _.compile(''); + var injector = ngInjector(input); + var model = injector.get(NgModel); expect(model.touched).toBe(false); expect(model.untouched).toBe(true); @@ -1475,15 +1401,15 @@ void main() { 'ng-model="model" ' 'ng-required="required" ' 'ng-pattern="pattern" ' - 'counting-validator ' - 'probe="i">'); + 'counting-validator>'); scope.context['pattern'] = '^[aeiou]+\$'; scope.context['required'] = true; scope.apply(); - var model = scope.context['i'].directive(NgModel); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); var counter = model.validators.firstWhere((validator) => validator.name == 'counting'); // TODO(#881): There is a bug in ngModel where the validators are validated too often. @@ -1506,15 +1432,15 @@ void main() { 'ng-required="required" ' 'ng-pattern="pattern" ' 'counting-validator ' - 'ng-model="model" ' - 'probe="i">'); + 'ng-model="model">'); scope.context['pattern'] = '^[aeiou]+\$'; scope.context['required'] = true; scope.apply(); - var model = scope.context['i'].directive(NgModel); + var injector = ngInjector('input', _.rootElement); + var model = injector.get(NgModel); var counter = model.validators.firstWhere((validator) => validator.name == 'counting'); @@ -1527,12 +1453,12 @@ void main() { describe('converters', () { it('should parse the model value according to the given parser', (Scope scope) { - _.compile(''); + var input = _.compile(''); scope.apply(); var probe = scope.context['i']; - var input = probe.element; - var model = probe.directive(NgModel); + var injector = ngInjector(input); + var model = injector.get(NgModel); model.converter = new LowercaseValueParser(); input.value = 'HELLO'; @@ -1544,12 +1470,11 @@ void main() { }); it('should format the model value according to the given formatter', (Scope scope) { - _.compile(''); + var input = _.compile(''); scope.apply(); - var probe = scope.context['i']; - var input = probe.element; - var model = probe.directive(NgModel); + var injector = ngInjector(input); + var model = injector.get(NgModel); model.converter = new UppercaseValueFormatter(); scope.apply(() { @@ -1562,18 +1487,16 @@ void main() { it('should retain the current input value if the parser fails', (Scope scope) { _.compile('
' + - ' ' + - ' ' + + ' ' + + ' ' + '
'); scope.apply(); - var probe1 = scope.context['i']; - var input1 = probe1.element; - var model1 = probe1.directive(NgModel); - - var probe2 = scope.context['j']; - var input2 = probe2.element; - var model2 = probe2.directive(NgModel); + var inputs = ngQuery(_.rootElement, 'input'); + var input1 = inputs[0]; + var model1 = ngInjector(input1).get(NgModel); + var input2 = inputs[1]; + var model2 = ngInjector(input2).get(NgModel); model1.converter = new FailedValueParser(); @@ -1591,12 +1514,10 @@ void main() { }); it('should reformat the viewValue when the formatter is changed', (Scope scope) { - _.compile(''); + var input = _.compile(''); scope.apply(); - var probe = scope.context['i']; - var input = probe.element; - var model = probe.directive(NgModel); + var model = ngInjector(input).get(NgModel); model.converter = new LowercaseValueParser(); input.value = 'HI THERE'; diff --git a/test/directive/ng_model_validators_spec.dart b/test/directive/ng_model_validators_spec.dart index 3aa9d54ee..2e9d66334 100644 --- a/test/directive/ng_model_validators_spec.dart +++ b/test/directive/ng_model_validators_spec.dart @@ -21,9 +21,9 @@ void main() { describe('required', () { it('should validate the input field if the required attribute is set', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(false); @@ -39,9 +39,8 @@ void main() { it('should validate a number input field if the required attribute is set', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); _.rootScope.apply(); @@ -58,9 +57,8 @@ void main() { it('should validate the input field depending on if ng-required is true', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); _.rootScope.apply(); @@ -88,9 +86,8 @@ void main() { describe('[type="url"]', () { it('should validate the input field given a valid or invalid URL', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); expect(model.valid).toEqual(true); expect(model.invalid).toEqual(false); @@ -113,9 +110,8 @@ void main() { describe('[type="email"]', () { it('should validate the input field given a valid or invalid email address', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -144,9 +140,8 @@ void main() { ['range', 'number'], (type) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -182,9 +177,8 @@ void main() { ['range', 'number'], (type) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); _.rootScope.apply(() { _.rootScope.context['val'] = "8"; @@ -219,9 +213,8 @@ void main() { ['range', 'number'], (type) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); //should be valid even when no number is present model.validate(); @@ -261,9 +254,8 @@ void main() { ['range', 'number'], (type) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); _.rootScope.apply(() { _.rootScope.context['val'] = "8"; @@ -298,9 +290,8 @@ void main() { ['range', 'number'], (type) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); //should be valid even when no number is present model.validate(); @@ -339,9 +330,8 @@ void main() { describe('pattern', () { it('should validate the input field if a ng-pattern attribute is provided', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -376,9 +366,8 @@ void main() { }); it('should validate the input field if a pattern attribute is provided', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -412,9 +401,8 @@ void main() { describe('minlength', () { it('should validate the input field if a minlength attribute is provided', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -438,9 +426,8 @@ void main() { }); it('should validate the input field if a ng-minlength attribute is provided', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -468,9 +455,8 @@ void main() { describe('maxlength', () { it('should validate the input field if a maxlength attribute is provided', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -494,9 +480,8 @@ void main() { }); it('should validate the input field if a ng-maxlength attribute is provided', (RootScope scope) { - _.compile(''); - Probe probe = _.rootScope.context['i']; - var model = probe.directive(NgModel); + _.compile(''); + var model = ngInjector('input', _.rootElement).get(NgModel); model.validate(); expect(model.valid).toEqual(true); @@ -527,8 +512,8 @@ void main() { beforeEach(() { scope = _.rootScope; build = (attr, type) { - input = _.compile(''); - model = scope.context['p'].directive(NgModel); + input = _.compile(''); + model = ngInjector(input).get(NgModel); }; }); @@ -627,6 +612,6 @@ void main() { expect(model.valid).toBe(true); }); - }); + }); }); } diff --git a/test/directive/ng_switch_spec.dart b/test/directive/ng_switch_spec.dart index e289113aa..ed8c9e1e3 100644 --- a/test/directive/ng_switch_spec.dart +++ b/test/directive/ng_switch_spec.dart @@ -170,24 +170,29 @@ void main() { it('should properly create and destroy child scopes', () { var element = _.compile( - '
' + - '
{{name}}
' + + '
' + '
{{name}}
' '
'); _.rootScope.apply(); - var getChildScope = () => _.rootScope.context['probe'] == null ? - null : _.rootScope.context['probe'].scope; + var getChildScope = () { + try { + return ngScope('[ng-switch-when]', element); + } catch (e) { + return null; + } + }; expect(getChildScope()).toBeNull(); _.rootScope.context['url'] = 'a'; _.rootScope.context['name'] = 'works'; _.rootScope.apply(); - var child1 = getChildScope(); - expect(child1).toBeNotNull(); + var childScope1 = getChildScope(); + expect(childScope1).toBeNotNull(); expect(element.text).toEqual('works'); var destroyListener = guinness.createSpy('watch listener'); - var watcher = child1.on(ScopeEvent.DESTROY).listen(destroyListener); + var watcher = childScope1.on(ScopeEvent.DESTROY).listen(destroyListener); _.rootScope.context['url'] = 'x'; _.rootScope.apply(); @@ -197,9 +202,9 @@ void main() { _.rootScope.context['url'] = 'a'; _.rootScope.apply(); - var child2 = getChildScope(); - expect(child2).toBeDefined(); - expect(child2).not.toBe(child1); + var childScope2 = getChildScope(); + expect(childScope2).toBeDefined(); + expect(childScope2).not.toBe(childScope1); }); }); } diff --git a/test/introspection_spec.dart b/test/introspection_spec.dart index a034d7073..289a4b946 100644 --- a/test/introspection_spec.dart +++ b/test/introspection_spec.dart @@ -35,17 +35,32 @@ void main() { it('should select probe using CSS selector', (TestBed _) { _.compile('
WORKS
'); document.body.append(_.rootElement); - var div = new Element.html('

'); - var span = div.querySelector('span'); - var shadowRoot = span.createShadowRoot(); - shadowRoot.innerHtml = '
  • stash
  • secret
    • '; - ElementProbe probe = ngProbe('[ng-show]'); expect(probe).toBeDefined(); expect(probe.injector.get(NgShow) is NgShow).toEqual(true); _.rootElement.remove(); }); + it('should throw if the root Element is attached to the DOM', (TestBed _) { + _.compile('
      WORKS
      '); + document.body.append(_.rootElement); + expect(() => ngProbe('[ng-show]', _.rootElement)) + .toThrow("The root element must not be attached to the DOM"); + }); + + it('should select probe using CSS selector inside the given root element',(TestBed _) { + _.compile('
      WORKS
      '); + ElementProbe probe = ngProbe('[ng-show]', _.rootElement); + expect(probe).toBeDefined(); + expect(probe.injector.get(NgShow) is NgShow).toEqual(true); + }); + + it('should throw when the selector does not match any element', (TestBed _) { + _.compile('
      '); + expect(() => ngProbe('input')) + .toThrow("The 'input' selector does not match any node"); + }); + it('should select elements in the root shadow root', () { var div = new Element.html('
      '); var shadowRoot = div.createShadowRoot(); diff --git a/test/mock/test_bed_spec.dart b/test/mock/test_bed_spec.dart index a35872f5f..c336c7ba0 100644 --- a/test/mock/test_bed_spec.dart +++ b/test/mock/test_bed_spec.dart @@ -18,15 +18,10 @@ void main() { inject((Scope scope) { Scope childScope = scope.createChild({}); - - _.compile('
      ', scope: childScope); - - Probe probe = _.rootScope.context['i']; - var directiveInst = probe.directive(MyTestBedDirective); - + var div = _.compile('
      ', scope: childScope); + var injector = ngInjector(div); childScope.destroy(); - - expect(directiveInst.destroyed).toBe(true); + expect(injector.get(MyTestBedDirective).destroyed).toBe(true); }); }); diff --git a/test/routing/ng_bind_route_spec.dart b/test/routing/ng_bind_route_spec.dart index a3351b863..b861b8e88 100644 --- a/test/routing/ng_bind_route_spec.dart +++ b/test/routing/ng_bind_route_spec.dart @@ -19,16 +19,14 @@ main() { it('should inject null RouteProvider when no ng-bind-route', async(() { - Element root = _.compile('
      '); - expect(_.rootScope.context['routeProbe'].injector.get(RouteProvider)).toBeNull(); + Element root = _.compile('
      '); + expect(ngInjector('div', root).get(RouteProvider)).toBeNull(); })); it('should inject RouteProvider with correct flat route', async(() { - Element root = _.compile( - '
      '); - expect(_.rootScope.context['routeProbe'].injector.get(RouteProvider).routeName) - .toEqual('library'); + Element root = _.compile('
      '); + expect(ngInjector('#target', root).get(RouteProvider).routeName).toEqual('library'); })); @@ -36,17 +34,15 @@ main() { Element root = _.compile( '
      ' '
      ' - '
      ' + '
      ' '
      ' '
      '); - expect(_.rootScope.context['routeProbe'].injector.get(RouteProvider).route.name) - .toEqual('all'); + expect(ngInjector('#target', root).get(RouteProvider).route.name).toEqual('all'); })); it('should expose NgBindRoute as RouteProvider', async(() { - Element root = _.compile( - '
      '); - expect(_.rootScope.context['routeProbe'].injector.get(RouteProvider) is NgBindRoute).toBeTruthy(); + Element root = _.compile('
      '); + expect(ngInjector('#target', root).get(RouteProvider) is NgBindRoute).toBeTruthy(); })); }); diff --git a/test/routing/ng_view_spec.dart b/test/routing/ng_view_spec.dart index 34bffa8f8..a16b4d77c 100644 --- a/test/routing/ng_view_spec.dart +++ b/test/routing/ng_view_spec.dart @@ -20,10 +20,8 @@ main() => describe('ngView', () { _ = tb; router = _router; - templates.put('foo.html', new HttpResponse(200, - '

      Foo

      ')); - templates.put('bar.html', new HttpResponse(200, - '

      Bar

      ')); + templates.put('foo.html', new HttpResponse(200, '

      Foo

      ')); + templates.put('bar.html', new HttpResponse(200, '

      Bar

      ')); }); @@ -45,13 +43,13 @@ main() => describe('ngView', () { })); it('should expose NgView as RouteProvider', async(() { - _.compile(''); + _.compile(''); router.route('/foo'); microLeap(); _.rootScope.apply(); Probe probe = _.rootScope.context['p']; - expect(probe.injector.get(RouteProvider) is NgView).toBeTruthy(); + expect(ngInjector('h1', _.rootElement).get(RouteProvider) is NgView).toBeTruthy(); }));