@@ -11,7 +11,8 @@ import {
11
11
getTableMissingMatchingRowDefError ,
12
12
getTableMissingRowDefsError ,
13
13
getTableMultipleDefaultRowDefsError ,
14
- getTableUnknownColumnError
14
+ getTableUnknownColumnError ,
15
+ getTableUnknownDataSourceError
15
16
} from './table-errors' ;
16
17
import { CdkHeaderRowDef , CdkRowDef } from './row' ;
17
18
import { CdkColumnDef } from './cell' ;
@@ -45,6 +46,7 @@ describe('CdkTable', () => {
45
46
BooleanRowCdkTableApp ,
46
47
WrapperCdkTableApp ,
47
48
OuterTableApp ,
49
+ CdkTableWithDifferentDataInputsApp ,
48
50
] ,
49
51
} ) . compileComponents ( ) ;
50
52
} ) ) ;
@@ -113,6 +115,138 @@ describe('CdkTable', () => {
113
115
} ) ;
114
116
} ) ;
115
117
118
+ describe ( 'with different data inputs other than data source' , ( ) => {
119
+ let dataInputFixture : ComponentFixture < CdkTableWithDifferentDataInputsApp > ;
120
+ let dataInputComponent : CdkTableWithDifferentDataInputsApp ;
121
+ let dataInputTableElement : HTMLElement ;
122
+
123
+ let baseData : TestData [ ] = [
124
+ { a : 'a_1' , b : 'b_1' , c : 'c_1' } ,
125
+ { a : 'a_2' , b : 'b_2' , c : 'c_2' } ,
126
+ { a : 'a_3' , b : 'b_3' , c : 'c_3' } ,
127
+ ] ;
128
+
129
+ beforeEach ( ( ) => {
130
+ dataInputFixture = TestBed . createComponent ( CdkTableWithDifferentDataInputsApp ) ;
131
+ dataInputComponent = dataInputFixture . componentInstance ;
132
+ dataInputFixture . detectChanges ( ) ;
133
+
134
+ dataInputTableElement = dataInputFixture . nativeElement . querySelector ( 'cdk-table' ) ;
135
+ } ) ;
136
+
137
+ it ( 'should render with data array input' , ( ) => {
138
+ const data = baseData . slice ( ) ;
139
+ dataInputComponent . dataSource = data ;
140
+ dataInputFixture . detectChanges ( ) ;
141
+
142
+ const expectedRender = [
143
+ [ 'Column A' , 'Column B' , 'Column C' ] ,
144
+ [ 'a_1' , 'b_1' , 'c_1' ] ,
145
+ [ 'a_2' , 'b_2' , 'c_2' ] ,
146
+ [ 'a_3' , 'b_3' , 'c_3' ] ,
147
+ ] ;
148
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
149
+
150
+ // Push data to the array but neglect to tell the table, should be no change
151
+ data . push ( { a : 'a_4' , b : 'b_4' , c : 'c_4' } ) ;
152
+
153
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
154
+
155
+ // Notify table of the change, expect another row
156
+ dataInputComponent . table . renderRows ( ) ;
157
+ dataInputFixture . detectChanges ( ) ;
158
+
159
+ expectedRender . push ( [ 'a_4' , 'b_4' , 'c_4' ] ) ;
160
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
161
+
162
+ // Remove a row and expect the change in rows
163
+ data . pop ( ) ;
164
+ dataInputComponent . table . renderRows ( ) ;
165
+
166
+ expectedRender . pop ( ) ;
167
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
168
+
169
+ // Remove the data input entirely and expect no rows - just header.
170
+ dataInputComponent . dataSource = null ;
171
+ dataInputFixture . detectChanges ( ) ;
172
+
173
+ expectTableToMatchContent ( dataInputTableElement , [ expectedRender [ 0 ] ] ) ;
174
+
175
+ // Add back the data to verify that it renders rows
176
+ dataInputComponent . dataSource = data ;
177
+ dataInputFixture . detectChanges ( ) ;
178
+
179
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
180
+ } ) ;
181
+
182
+ it ( 'should render with data stream input' , ( ) => {
183
+ const data = baseData . slice ( ) ;
184
+ const stream = new BehaviorSubject < TestData [ ] > ( data ) ;
185
+ dataInputComponent . dataSource = stream ;
186
+ dataInputFixture . detectChanges ( ) ;
187
+
188
+ const expectedRender = [
189
+ [ 'Column A' , 'Column B' , 'Column C' ] ,
190
+ [ 'a_1' , 'b_1' , 'c_1' ] ,
191
+ [ 'a_2' , 'b_2' , 'c_2' ] ,
192
+ [ 'a_3' , 'b_3' , 'c_3' ] ,
193
+ ] ;
194
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
195
+
196
+ // Push data to the array and emit the data array on the stream
197
+ data . push ( { a : 'a_4' , b : 'b_4' , c : 'c_4' } ) ;
198
+ stream . next ( data ) ;
199
+ dataInputFixture . detectChanges ( ) ;
200
+
201
+ expectedRender . push ( [ 'a_4' , 'b_4' , 'c_4' ] ) ;
202
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
203
+
204
+ // Push data to the array but rather than emitting, call renderRows.
205
+ data . push ( { a : 'a_5' , b : 'b_5' , c : 'c_5' } ) ;
206
+ dataInputComponent . table . renderRows ( ) ;
207
+ dataInputFixture . detectChanges ( ) ;
208
+
209
+ expectedRender . push ( [ 'a_5' , 'b_5' , 'c_5' ] ) ;
210
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
211
+
212
+ // Remove a row and expect the change in rows
213
+ data . pop ( ) ;
214
+ expectedRender . pop ( ) ;
215
+ stream . next ( data ) ;
216
+
217
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
218
+
219
+ // Remove the data input entirely and expect no rows - just header.
220
+ dataInputComponent . dataSource = null ;
221
+ dataInputFixture . detectChanges ( ) ;
222
+
223
+ expectTableToMatchContent ( dataInputTableElement , [ expectedRender [ 0 ] ] ) ;
224
+
225
+ // Add back the data to verify that it renders rows
226
+ dataInputComponent . dataSource = stream ;
227
+ dataInputFixture . detectChanges ( ) ;
228
+
229
+ expectTableToMatchContent ( dataInputTableElement , expectedRender ) ;
230
+ } ) ;
231
+
232
+ it ( 'should throw an error if the data source is not valid' , ( ) => {
233
+ dataInputComponent . dataSource = { invalid : 'dataSource' } ;
234
+
235
+ expect ( ( ) => dataInputFixture . detectChanges ( ) )
236
+ . toThrowError ( getTableUnknownDataSourceError ( ) . message ) ;
237
+ } ) ;
238
+
239
+ it ( 'should throw an error if the data source is not valid' , ( ) => {
240
+ dataInputComponent . dataSource = undefined ;
241
+ dataInputFixture . detectChanges ( ) ;
242
+
243
+ // Expect the table to render just the header, no rows
244
+ expectTableToMatchContent ( dataInputTableElement , [
245
+ [ 'Column A' , 'Column B' , 'Column C' ]
246
+ ] ) ;
247
+ } ) ;
248
+ } ) ;
249
+
116
250
it ( 'should render cells even if row data is falsy' , ( ) => {
117
251
const booleanRowCdkTableAppFixture = TestBed . createComponent ( BooleanRowCdkTableApp ) ;
118
252
const booleanRowCdkTableElement =
@@ -720,6 +854,36 @@ class SimpleCdkTableApp {
720
854
@ViewChild ( CdkTable ) table : CdkTable < TestData > ;
721
855
}
722
856
857
+ @Component ( {
858
+ template : `
859
+ <cdk-table [dataSource]="dataSource">
860
+ <ng-container cdkColumnDef="column_a">
861
+ <cdk-header-cell *cdkHeaderCellDef> Column A</cdk-header-cell>
862
+ <cdk-cell *cdkCellDef="let row"> {{row.a}}</cdk-cell>
863
+ </ng-container>
864
+
865
+ <ng-container cdkColumnDef="column_b">
866
+ <cdk-header-cell *cdkHeaderCellDef> Column B</cdk-header-cell>
867
+ <cdk-cell *cdkCellDef="let row"> {{row.b}}</cdk-cell>
868
+ </ng-container>
869
+
870
+ <ng-container cdkColumnDef="column_c">
871
+ <cdk-header-cell *cdkHeaderCellDef> Column C</cdk-header-cell>
872
+ <cdk-cell *cdkCellDef="let row"> {{row.c}}</cdk-cell>
873
+ </ng-container>
874
+
875
+ <cdk-header-row *cdkHeaderRowDef="columnsToRender"></cdk-header-row>
876
+ <cdk-row *cdkRowDef="let row; columns: columnsToRender"></cdk-row>
877
+ </cdk-table>
878
+ `
879
+ } )
880
+ class CdkTableWithDifferentDataInputsApp {
881
+ dataSource : DataSource < TestData > | Observable < TestData [ ] > | TestData [ ] | any = null ;
882
+ columnsToRender = [ 'column_a' , 'column_b' , 'column_c' ] ;
883
+
884
+ @ViewChild ( CdkTable ) table : CdkTable < TestData > ;
885
+ }
886
+
723
887
@Component ( {
724
888
template : `
725
889
<cdk-table [dataSource]="dataSource">
@@ -1186,6 +1350,9 @@ function expectTableToMatchContent(tableElement: Element, expectedTableContent:
1186
1350
}
1187
1351
}
1188
1352
1353
+ // Copy the expected data array to avoid mutating the test's array
1354
+ expectedTableContent = expectedTableContent . slice ( ) ;
1355
+
1189
1356
// Check header cells
1190
1357
const expectedHeaderContent = expectedTableContent . shift ( ) ;
1191
1358
getHeaderCells ( tableElement ) . forEach ( ( cell , index ) => {
@@ -1196,7 +1363,13 @@ function expectTableToMatchContent(tableElement: Element, expectedTableContent:
1196
1363
} ) ;
1197
1364
1198
1365
// Check data row cells
1199
- getRows ( tableElement ) . forEach ( ( row , rowIndex ) => {
1366
+ const rows = getRows ( tableElement ) ;
1367
+ if ( rows . length !== expectedTableContent . length ) {
1368
+ missedExpectations . push (
1369
+ `Expected ${ expectedTableContent . length } rows but found ${ rows . length } ` ) ;
1370
+ fail ( missedExpectations . join ( '\n' ) ) ;
1371
+ }
1372
+ rows . forEach ( ( row , rowIndex ) => {
1200
1373
getCells ( row ) . forEach ( ( cell , cellIndex ) => {
1201
1374
const expected = expectedTableContent . length ?
1202
1375
expectedTableContent [ rowIndex ] [ cellIndex ] :
0 commit comments