From fb00d849aed671fbc299c2b07f2170852603a78a Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Mon, 14 Jul 2014 22:40:47 +0100 Subject: [PATCH] docs(guide/unit-testing): add info on testing element transclude directives Closes #4505 --- docs/content/guide/unit-testing.ngdoc | 74 +++++++++++++++++++++++++++ src/ng/compile.js | 5 ++ 2 files changed, 79 insertions(+) diff --git a/docs/content/guide/unit-testing.ngdoc b/docs/content/guide/unit-testing.ngdoc index 0ca8bcea6f0c..d9bdb48a892f 100644 --- a/docs/content/guide/unit-testing.ngdoc +++ b/docs/content/guide/unit-testing.ngdoc @@ -337,6 +337,80 @@ We inject the $compile service and $rootScope before each jasmine test. The $com to render the aGreatEye directive. After rendering the directive we ensure that the directive has replaced the content and "lidless, wreathed in flame, 2 times" is present. +### Testing Transclusion Directives + +Directives that use transclusion are treated specially by the compiler. Before their compile +function is called, the contents of the directive's element are removed from the element and +provided via a transclusion function. The directive's template is then appended to the directive's +element, to which it can then insert the transcluded content into its template. + + +Before compilation: +``` +
+ Some transcluded content +
+``` + +After transclusion extraction: +``` +
+``` + +After compilation: +``` +
+ Some Template + Some transcluded content +
+``` + +If the directive is using 'element' transclusion then the compiler will actually remove the +directive's entire element from the DOM and replace it with a comment node. The template is +then inserted "after" this comment node. + +Before compilation +``` +
+ Some Content +
+``` + +After transclusion extraction +``` + +``` + +After compilation: +``` + +
+ Some Template + Some transcluded content +
+``` + +It is important to be aware of this when writing tests for directives that use 'element' +transclusion. If you place the directive on the root element of the DOM fragment that you +pass to {@link $compile}, then the DOM node returned from the linking function will be the +comment node and you will lose the ability to access the template and transcluded content. + +``` +var node = $compile('
')($rootScope); +expect(node[0].nodeType).toEqual(node.COMMENT_NODE); +expect(node[1]).toBeUndefined(); +``` + +To cope with this you simply ensure that your 'element' transclude directive is wrapped in an +element, such as a `
`. + +``` +var node = $compile('
')($rootScope); +var contents = node.contents(); +expect(contents[0].nodeType).toEqual(node.COMMENT_NODE); +expect(contents[1].nodeType).toEqual(node.ELEMENT_NODE); +``` + ### Testing Directives With External Templates If your directive uses `templateUrl`, consider using diff --git a/src/ng/compile.js b/src/ng/compile.js index 859e16934cfc..551a3139b0ae 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -266,6 +266,11 @@ * * `true` - transclude the content of the directive. * * `'element'` - transclude the whole element including any directives defined at lower priority. * + *
+ * **Note:** When testing an element transclude directive you must not place the directive at the root of the + * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives + * Testing Transclusion Directives}. + *
* * #### `compile` *