From 3ce56b739c7c1565e748f7a5eb6193d0f40fa902 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 Closes #8197 --- 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 0d5379da2..f10d9a8ff 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: +```html +
+ Some transcluded content +
+``` + +After transclusion extraction: +```html +
+``` + +After compilation: +```html +
+ Some Template + Some transcluded content +
+``` + +If the directive is using 'element' transclusion, the compiler will actually remove the +directive's entire element from the DOM and replace it with a comment node. The compiler then +inserts the directive's template "after" this comment node, as a sibling. + +Before compilation +```html +
+ Some Content +
+``` + +After transclusion extraction +```html + +``` + +After compilation: +```html + +
+ 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. + +```javascript +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 `
`. + +```javascript +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 8fbe18620..6ac7ba16a 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -253,6 +253,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` *