1
1
describe ( 'mdSubheader' , function ( ) {
2
2
var BASIC_SUBHEADER = '<md-subheader>Hello world!</md-subheader>' ;
3
- var pageScope , element , controller , contentElement ;
3
+ var pageScope , element , cloneElement , controller , contentElement ;
4
4
var $rootScope , $timeout , $exceptionHandler ;
5
5
6
- beforeEach ( module ( 'material.components.subheader' ) ) ;
6
+ beforeEach ( module ( 'material.components.subheader' , function ( $provide ) {
7
+ $provide . decorator ( '$mdUtil' , function ( $delegate ) {
8
+
9
+ // We always return nothing on the checkStickySupport method to test the functionality of the subheaders
10
+ // with the sticky clones behavior.
11
+ $delegate . checkStickySupport = angular . noop ;
12
+
13
+ return $delegate ;
14
+ } )
15
+ } ) ) ;
7
16
8
17
beforeEach ( inject ( function ( $injector ) {
9
18
$rootScope = $injector . get ( '$rootScope' ) ;
@@ -45,34 +54,47 @@ describe('mdSubheader', function() {
45
54
it ( 'applies the theme to the header and clone' , function ( ) {
46
55
build ( '<div md-theme="somethingElse">' + BASIC_SUBHEADER + '</div>' ) ;
47
56
48
- // The subheader now wraps the clone in a DIV in case of ng-if usage, so we have to search for
49
- // the proper element.
50
- var clone = getCloneElement ( ) ;
51
-
52
- expect ( getSubheader ( ) . classList ) . toContain ( 'md-somethingElse-theme' ) ;
53
- expect ( getSubheader ( clone ) . classList ) . toContain ( 'md-somethingElse-theme' ) ;
57
+ expect ( getElement ( ) ) . toHaveClass ( 'md-somethingElse-theme' ) ;
58
+ expect ( getCloneElement ( ) ) . toHaveClass ( 'md-somethingElse-theme' ) ;
54
59
} ) ;
55
60
56
61
it ( 'applies the proper scope to the clone' , function ( ) {
57
- build ( '<div><md-subheader>Hello {{ to }}!</md-subheader></div>' ) ;
62
+ build (
63
+ '<div>' +
64
+ '<md-subheader>Hello {{ to }}!</md-subheader>' +
65
+ '</div>' ) ;
58
66
59
67
pageScope . to = 'world' ;
60
68
pageScope . $apply ( ) ;
61
69
62
- var clone = getCloneElement ( ) ;
63
-
64
- expect ( getSubheader ( ) . textContent . trim ( ) ) . toEqual ( 'Hello world!' ) ;
65
- expect ( getSubheader ( clone ) . textContent . trim ( ) ) . toEqual ( 'Hello world!' ) ;
70
+ expect ( getElement ( ) [ 0 ] . textContent . trim ( ) ) . toEqual ( 'Hello world!' ) ;
71
+ expect ( getCloneElement ( ) [ 0 ] . textContent . trim ( ) ) . toEqual ( 'Hello world!' ) ;
66
72
} ) ;
67
73
68
74
it ( 'supports ng-if' , function ( ) {
69
- build ( '<div><md-subheader ng-if="true">test</md-subheader></div>' ) ;
75
+ build (
76
+ '<div>' +
77
+ '<md-subheader ng-if="isAdded">test</md-subheader>' +
78
+ '</div>'
79
+ ) ;
70
80
81
+ expect ( isCloneShowing ( ) ) . toBeFalsy ( ) ;
82
+
83
+ pageScope . $apply ( 'isAdded = true' ) ;
84
+ $timeout . flush ( ) ;
85
+
86
+ expect ( isCloneShowing ( ) ) . toBeTruthy ( ) ;
87
+
88
+ // Check if there were no exceptions caused.
71
89
expect ( $exceptionHandler . errors ) . toEqual ( [ ] ) ;
72
- expect ( element [ 0 ] . querySelectorAll ( '.md-subheader' ) . length ) . toEqual ( 1 ) ;
90
+
91
+ function isCloneShowing ( ) {
92
+ var clone = getCloneElement ( ) ;
93
+ return clone . length && ! ! clone [ 0 ] . parentNode ;
94
+ }
73
95
} ) ;
74
96
75
- it ( 'should support ng-if inside of stickyClone ' , function ( ) {
97
+ it ( 'should support ng-if inside of the sticky clone ' , function ( ) {
76
98
build (
77
99
'<div>' +
78
100
'<md-subheader>' +
@@ -91,6 +113,38 @@ describe('mdSubheader', function() {
91
113
expect ( clone . textContent . trim ( ) ) . toBe ( 'FooBar' ) ;
92
114
} ) ;
93
115
116
+ it ( 'should support ng-show on the sticky clone' , function ( ) {
117
+ build (
118
+ '<div>' +
119
+ '<md-subheader ng-show="isShowing">Subheader</md-subheader>' +
120
+ '</div>'
121
+ ) ;
122
+
123
+ var clone = getCloneElement ( ) ;
124
+
125
+ expect ( clone ) . toHaveClass ( 'ng-hide' ) ;
126
+
127
+ pageScope . $apply ( 'isShowing = true' ) ;
128
+
129
+ expect ( clone ) . not . toHaveClass ( 'ng-hide' ) ;
130
+ } ) ;
131
+
132
+ it ( 'should support ng-hide on the sticky clone' , function ( ) {
133
+ build (
134
+ '<div>' +
135
+ '<md-subheader ng-hide="isHidden">Subheader</md-subheader>' +
136
+ '</div>'
137
+ ) ;
138
+
139
+ var clone = getCloneElement ( ) ;
140
+
141
+ expect ( clone ) . not . toHaveClass ( 'ng-hide' ) ;
142
+
143
+ pageScope . $apply ( 'isHidden = true' ) ;
144
+
145
+ expect ( clone ) . toHaveClass ( 'ng-hide' ) ;
146
+ } ) ;
147
+
94
148
it ( 'should work with a ng-if directive inside of the stickyClone' , function ( ) {
95
149
build (
96
150
'<div>' +
@@ -106,10 +160,18 @@ describe('mdSubheader', function() {
106
160
} ) ;
107
161
108
162
it ( 'supports ng-repeat' , function ( ) {
109
- build ( '<div><md-subheader ng-repeat="i in [1,2,3]">Test {{i}}</md-subheader></div>' ) ;
163
+ build (
164
+ '<div>' +
165
+ '<md-subheader ng-repeat="i in [1, 2, 3]">Test {{i}}</md-subheader>' +
166
+ '</div>'
167
+ ) ;
168
+
169
+ // TODO(devversion): Remove this expectation and update to correctly detect 6 subheaders
170
+ // TODO(devversion) See related issue: https://github.com/angular/material/issues/8647
171
+ expect ( contentElement [ 0 ] . querySelectorAll ( '.md-subheader' ) . length ) . toEqual ( 12 ) ;
110
172
173
+ // Check if there were no exceptions caused.
111
174
expect ( $exceptionHandler . errors ) . toEqual ( [ ] ) ;
112
- expect ( element [ 0 ] . querySelectorAll ( '.md-subheader' ) . length ) . toEqual ( 3 ) ;
113
175
} ) ;
114
176
115
177
function build ( template ) {
@@ -121,30 +183,39 @@ describe('mdSubheader', function() {
121
183
// Flush the timeout, which prepends the sticky clone to the md-content.
122
184
$timeout . flush ( ) ;
123
185
124
- // When the contentElement only has only one children then the current
125
- // browser supports sticky elements natively.
126
- if ( contentElement . children ( ) . length === 1 ) {
127
- element = getCloneElement ( ) ;
128
- } else {
129
- // When the browser doesn't support sticky elements natively we will have a sticky clone.
130
- // The sticky clone element will be always prepended, which means that we have to use the child
131
- // at the second position.
132
- element = contentElement . children ( ) . eq ( 1 ) ;
133
- }
186
+ element = getElement ( ) ;
187
+ cloneElement = getCloneElement ( ) ;
134
188
135
189
controller = element . controller ( 'mdSubheader' ) ;
136
190
137
191
pageScope . $apply ( ) ;
192
+
193
+ // Flush the timeouts for ngIf and ngRepeat, because those will be added within the
194
+ // next tick of the subheader tranclusion.
138
195
$timeout . flush ( ) ;
139
196
} ) ;
140
197
}
141
198
142
- function getSubheader ( el ) {
143
- return ( el || element ) [ 0 ] . querySelector ( '.md-subheader' ) ;
144
- }
145
-
146
199
function getCloneElement ( ) {
147
- // The clone element will be always prepended, which means that we have to get the child at index zero.
148
- return contentElement . children ( ) . eq ( 0 ) ;
200
+ // We search for the clone element by using the _md-sticky-clone class, which will be automatically added
201
+ // by the $mdSticky service.
202
+ return angular . element ( contentElement [ 0 ] . querySelector ( '._md-sticky-clone .md-subheader' ) ) ;
149
203
}
204
+
205
+ function getElement ( ) {
206
+ // The *real* element can be found, by search for a subheader, which doesn't have a parent with a unique class,
207
+ // which indicates a $mdSticky clone element.
208
+ var items = contentElement [ 0 ] . querySelectorAll ( '.md-subheader' ) ;
209
+
210
+ return angular . element ( checkSubheader ( 0 ) ) ;
211
+
212
+ function checkSubheader ( index ) {
213
+ var item = items [ index ] ;
214
+ if ( ! item ) return ;
215
+
216
+ return item . parentNode . classList . contains ( '_md-sticky-clone' ) ? checkSubheader ( index + 1 ) : item ;
217
+ }
218
+ }
219
+
220
+
150
221
} ) ;
0 commit comments