From eb057c384bdc6f6112c0c92536b134cd13ab76be Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 28 Apr 2014 16:51:51 +0200 Subject: [PATCH] feat(debug): Make ngProbe accept a CSS selector Closes #970 --- lib/application.dart | 2 +- lib/introspection.dart | 35 +++++++++++++++++++++-------------- lib/introspection_js.dart | 13 ++++++++----- test/introspection_spec.dart | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/lib/application.dart b/lib/application.dart index 8cdf7a2ea..17a5bdfe2 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -126,7 +126,7 @@ class AngularModule extends Module { */ abstract class Application { static _find(String selector, [dom.Element defaultElement]) { - var element = dom.window.document.querySelector(selector); + var element = dom.document.querySelector(selector); if (element == null) element = defaultElement; if (element == null) { throw "Could not find application element '$selector'."; diff --git a/lib/introspection.dart b/lib/introspection.dart index 2245a4414..7293dd45d 100644 --- a/lib/introspection.dart +++ b/lib/introspection.dart @@ -10,26 +10,36 @@ import 'package:angular/core/module_internal.dart'; import 'package:angular/core_dom/module_internal.dart'; /** - * Return the closest [ElementProbe] object for a given [Element]. + * Return the [ElementProbe] object for the closest [Element] in the hierarchy. + * + * The node parameter could be: + * * a [dom.Node], + * * a CSS selector for this node. * * **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(dom.Node node) { - if (node == null) { - throw "ngProbe called without node"; +ElementProbe ngProbe(nodeOrSelector) { + var errorMsg; + var node; + if (nodeOrSelector == null) throw "ngProbe called without node"; + if (nodeOrSelector is String) { + var nodes = ngQuery(dom.document, nodeOrSelector); + if (nodes.isNotEmpty) node = nodes.first; + errorMsg = "Could not find a probe for the selector '$nodeOrSelector' nor its parents"; + } else { + node = nodeOrSelector; + errorMsg = "Could not find a probe for the node '$node' nor its parents"; } - var origNode = node; while (node != null) { var probe = elementExpando[node]; if (probe != null) return probe; node = node.parent; } - throw "Could not find a probe for [$origNode]"; + throw errorMsg; } - /** * Return the [Injector] associated with a current [Element]. * @@ -37,7 +47,7 @@ ElementProbe ngProbe(dom.Node node) { * application from the browser's REPL, unit or end-to-end tests. The function * is not intended to be called from Angular application. */ -Injector ngInjector(dom.Node node) => ngProbe(node).injector; +Injector ngInjector(nodeOrSelector) => ngProbe(nodeOrSelector).injector; /** @@ -47,7 +57,7 @@ Injector ngInjector(dom.Node node) => ngProbe(node).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(dom.Node node) => ngProbe(node).scope; +Scope ngScope(nodeOrSelector) => ngProbe(nodeOrSelector).scope; List ngQuery(dom.Node element, String selector, @@ -70,14 +80,11 @@ List ngQuery(dom.Node element, String selector, } /** - * Return a List of directive controllers associated with a current [Element]. + * Return a List of directives associated with a current [Element]. * * **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. */ -List ngDirectives(dom.Node node) { - ElementProbe probe = elementExpando[node]; - return probe == null ? [] : probe.directives; -} +List ngDirectives(nodeOrSelector) => ngProbe(nodeOrSelector).directives; diff --git a/lib/introspection_js.dart b/lib/introspection_js.dart index 5ea3be268..9ab32732a 100644 --- a/lib/introspection_js.dart +++ b/lib/introspection_js.dart @@ -17,11 +17,14 @@ var elementExpando = new Expando('element'); publishToJavaScript() { js.context - ..['ngProbe'] = new js.JsFunction.withThis((_, dom.Node node) => _jsProbe(ngProbe(node))) - ..['ngInjector'] = new js.JsFunction.withThis((_, dom.Node node) => _jsInjector(ngInjector(node))) - ..['ngScope'] = new js.JsFunction.withThis((_, dom.Node node) => _jsScope(ngScope(node), ngProbe(node).injector.get(ScopeStatsConfig))) + ..['ngProbe'] = new js.JsFunction.withThis((_, nodeOrSelector) => + _jsProbe(ngProbe(nodeOrSelector))) + ..['ngInjector'] = new js.JsFunction.withThis((_, nodeOrSelector) => + _jsInjector(ngInjector(nodeOrSelector))) + ..['ngScope'] = new js.JsFunction.withThis((_, nodeOrSelector) => + _jsScope(ngScope(nodeOrSelector), ngProbe(nodeOrSelector).injector.get(ScopeStatsConfig))) ..['ngQuery'] = new js.JsFunction.withThis((_, dom.Node node, String selector, [String containsText]) => - new js.JsArray.from(ngQuery(node, selector, containsText))); + new js.JsArray.from(ngQuery(node, selector, containsText))); } js.JsObject _jsProbe(ElementProbe probe) { @@ -34,7 +37,7 @@ js.JsObject _jsProbe(ElementProbe probe) { } js.JsObject _jsInjector(Injector injector) => -new js.JsObject.jsify({"get": injector.get})..['_dart_'] = injector; + new js.JsObject.jsify({"get": injector.get})..['_dart_'] = injector; js.JsObject _jsScope(Scope scope, ScopeStatsConfig config) { return new js.JsObject.jsify({ diff --git a/test/introspection_spec.dart b/test/introspection_spec.dart index a4ea5811e..d8ff35c74 100644 --- a/test/introspection_spec.dart +++ b/test/introspection_spec.dart @@ -3,6 +3,7 @@ library introspection_spec; import '_specs.dart'; import 'dart:js' as js; import 'package:angular/application_factory.dart'; +import 'dart:html'; void main() { describe('introspection', () { @@ -31,6 +32,20 @@ void main() { expect(toHtml(ngQuery(div, 'li', 'xxx'))).toEqual(''); }); + 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 select elements in the root shadow root', () { var div = new Element.html('
      '); var shadowRoot = div.createShadowRoot();