@@ -2,20 +2,24 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
2
2
import { fakeAsync , flush } from '@angular/core/testing' ;
3
3
import { IconLibraryTestingModule } from '@hypertrace/assets-library' ;
4
4
import { NavigationService } from '@hypertrace/common' ;
5
- import { SelectComponent , SelectModule } from '@hypertrace/components' ;
5
+ import { InputModule , LetAsyncModule , SelectComponent , SelectModule } from '@hypertrace/components' ;
6
6
import { byText , createHostFactory , mockProvider } from '@ngneat/spectator/jest' ;
7
7
import { EMPTY , of } from 'rxjs' ;
8
- import { AttributeMetadata } from '../../../graphql/model/metadata/attribute-metadata' ;
8
+ import { AttributeMetadata , AttributeMetadataType } from '../../../graphql/model/metadata/attribute-metadata' ;
9
9
import { ObservabilityTraceType } from '../../../graphql/model/schema/observability-traces' ;
10
10
import { MetadataService } from '../../../services/metadata/metadata.service' ;
11
11
import { ExploreQueryGroupByEditorComponent } from './explore-query-group-by-editor.component' ;
12
12
13
13
describe ( 'Explore Query Group by Editor component' , ( ) => {
14
14
// Define metadata at top level so equality checks always get same values
15
- const attributeMetadata = [ { name : 'test value' } , { name : 'foo bar' } ] ;
15
+ const attributeMetadata = [
16
+ { name : 'test value' , type : AttributeMetadataType . String } ,
17
+ { name : 'foo bar' , type : AttributeMetadataType . String } ,
18
+ { name : 'test map' , type : AttributeMetadataType . StringMap }
19
+ ] ;
16
20
const hostBuilder = createHostFactory ( {
17
21
component : ExploreQueryGroupByEditorComponent ,
18
- imports : [ SelectModule , HttpClientTestingModule , IconLibraryTestingModule ] ,
22
+ imports : [ SelectModule , HttpClientTestingModule , IconLibraryTestingModule , LetAsyncModule , InputModule ] ,
19
23
providers : [
20
24
mockProvider ( MetadataService , {
21
25
getAttributeDisplayName : ( attribute : AttributeMetadata ) => attribute . name ,
@@ -29,13 +33,11 @@ describe('Explore Query Group by Editor component', () => {
29
33
} ) ;
30
34
31
35
test ( 'sets group by to none if undefined provided' , fakeAsync ( ( ) => {
32
- const spectator = hostBuilder (
33
- `
36
+ const spectator = hostBuilder ( `
34
37
<ht-explore-query-group-by-editor
35
- context="${ ObservabilityTraceType . Api } " [groupByKey ]="groupBy "
38
+ context="${ ObservabilityTraceType . Api } " [groupByExpression ]="groupByExpression "
36
39
></ht-explore-query-group-by-editor>
37
- `
38
- ) ;
40
+ ` ) ;
39
41
spectator . tick ( ) ;
40
42
41
43
expect ( spectator . query ( SelectComponent ) ! . selected ) . toBeUndefined ( ) ;
@@ -46,38 +48,38 @@ describe('Explore Query Group by Editor component', () => {
46
48
const spectator = hostBuilder (
47
49
`
48
50
<ht-explore-query-group-by-editor
49
- context="${ ObservabilityTraceType . Api } " [groupByKey ]="groupByKey "
51
+ context="${ ObservabilityTraceType . Api } " [groupByExpression ]="groupByExpression "
50
52
></ht-explore-query-group-by-editor>
51
53
` ,
52
54
{
53
55
hostProps : {
54
- groupByKey : 'test value'
56
+ groupByExpression : { key : 'test value' }
55
57
}
56
58
}
57
59
) ;
58
60
59
- expect ( spectator . query ( SelectComponent ) ! . selected ) . toBe ( 'test value' ) ;
61
+ expect ( spectator . query ( SelectComponent ) ! . selected ) . toEqual ( attributeMetadata [ 0 ] ) ;
60
62
} ) ;
61
63
62
64
test ( 'updates if new group by is provided' , ( ) => {
63
65
const spectator = hostBuilder (
64
66
`
65
67
<ht-explore-query-group-by-editor
66
- context="${ ObservabilityTraceType . Api } " [groupByKey ]="groupByKey "
68
+ context="${ ObservabilityTraceType . Api } " [groupByExpression ]="groupByExpression "
67
69
></ht-explore-query-group-by-editor>
68
70
` ,
69
71
{
70
72
hostProps : {
71
- groupByKey : 'test value'
73
+ groupByExpression : { key : 'test value' }
72
74
}
73
75
}
74
76
) ;
75
77
76
- spectator . setHostInput ( { groupByKey : 'foo bar' } ) ;
78
+ spectator . setHostInput ( { groupByExpression : { key : 'foo bar' } } ) ;
77
79
78
- expect ( spectator . query ( SelectComponent ) ! . selected ) . toBe ( 'foo bar' ) ;
80
+ expect ( spectator . query ( SelectComponent ) ! . selected ) . toEqual ( attributeMetadata [ 1 ] ) ;
79
81
80
- spectator . setHostInput ( { groupByKey : undefined } ) ;
82
+ spectator . setHostInput ( { groupByExpression : undefined } ) ;
81
83
82
84
expect ( spectator . query ( SelectComponent ) ! . selected ) . toBeUndefined ( ) ;
83
85
} ) ;
@@ -87,12 +89,42 @@ describe('Explore Query Group by Editor component', () => {
87
89
const spectator = hostBuilder (
88
90
`
89
91
<ht-explore-query-group-by-editor
90
- context="${ ObservabilityTraceType . Api } " [groupByKey]="groupByKey" (groupByKeyChange)="onChange($event)"
92
+ context="${ ObservabilityTraceType . Api } " [groupByExpression]="groupByExpression" (groupByExpressionChange)="onChange($event)"
93
+ ></ht-explore-query-group-by-editor>
94
+ ` ,
95
+ {
96
+ hostProps : {
97
+ groupByExpression : { key : 'test value' } ,
98
+ onChange : onChange
99
+ }
100
+ }
101
+ ) ;
102
+ spectator . tick ( ) ; // Needs to tick to interact with select which is async
103
+
104
+ spectator . click ( spectator . query ( byText ( 'test value' ) ) ! ) ;
105
+
106
+ const options = spectator . queryAll ( '.select-option' , { root : true } ) ;
107
+ expect ( options . length ) . toBe ( 4 ) ;
108
+ spectator . click ( options [ 2 ] ) ;
109
+
110
+ spectator . tick ( 500 ) ; // 500ms debounce after group by change
111
+ expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
112
+ expect ( onChange ) . toHaveBeenCalledWith ( { key : 'foo bar' } ) ;
113
+
114
+ flush ( ) ; // Overlay removes async
115
+ } ) ) ;
116
+
117
+ test ( 'emits when group by key is changed' , fakeAsync ( ( ) => {
118
+ const onChange = jest . fn ( ) ;
119
+ const spectator = hostBuilder (
120
+ `
121
+ <ht-explore-query-group-by-editor
122
+ context="${ ObservabilityTraceType . Api } " [groupByExpression]="groupByExpression" (groupByExpressionChange)="onChange($event)"
91
123
></ht-explore-query-group-by-editor>
92
124
` ,
93
125
{
94
126
hostProps : {
95
- groupByKey : 'test value' ,
127
+ groupByExpression : { key : 'test value' } ,
96
128
onChange : onChange
97
129
}
98
130
}
@@ -102,12 +134,70 @@ describe('Explore Query Group by Editor component', () => {
102
134
spectator . click ( spectator . query ( byText ( 'test value' ) ) ! ) ;
103
135
104
136
const options = spectator . queryAll ( '.select-option' , { root : true } ) ;
105
- expect ( options . length ) . toBe ( 3 ) ;
137
+ expect ( options . length ) . toBe ( 4 ) ;
106
138
spectator . click ( options [ 2 ] ) ;
107
139
140
+ spectator . tick ( 500 ) ; // 500ms debounce after group by change
108
141
expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
109
- expect ( onChange ) . toHaveBeenCalledWith ( 'foo bar' ) ;
142
+ expect ( onChange ) . toHaveBeenCalledWith ( { key : 'foo bar' } ) ;
143
+
144
+ flush ( ) ; // Overlay removes async
145
+ } ) ) ;
146
+
147
+ test ( 'shows subpath for map attributes only' , fakeAsync ( ( ) => {
148
+ const spectator = hostBuilder (
149
+ `
150
+ <ht-explore-query-group-by-editor
151
+ context="${ ObservabilityTraceType . Api } " [groupByExpression]="groupByExpression"
152
+ ></ht-explore-query-group-by-editor>
153
+ ` ,
154
+ {
155
+ hostProps : {
156
+ groupByExpression : { key : 'test value' }
157
+ }
158
+ }
159
+ ) ;
160
+ spectator . tick ( ) ; // Needs to tick to interact with select which is async
161
+
162
+ expect ( spectator . query ( '.select' ) ) . toHaveText ( 'test value' ) ;
163
+ expect ( spectator . query ( '.group-by-path-input' ) ) . not . toExist ( ) ;
164
+ spectator . click ( spectator . query ( byText ( 'test value' ) ) ! ) ;
165
+ const options = spectator . queryAll ( '.select-option' , { root : true } ) ;
166
+ spectator . click ( options [ 3 ] ) ;
167
+
168
+ expect ( spectator . query ( '.group-by-path-input' ) ) . toExist ( ) ;
169
+
170
+ flush ( ) ; // Overlay removes async
171
+ } ) ) ;
110
172
173
+ test ( 'outputs map expressions correctly' , fakeAsync ( ( ) => {
174
+ const onChange = jest . fn ( ) ;
175
+ const spectator = hostBuilder (
176
+ `
177
+ <ht-explore-query-group-by-editor
178
+ context="${ ObservabilityTraceType . Api } " (groupByExpressionChange)="onChange($event)"
179
+ ></ht-explore-query-group-by-editor>
180
+ ` ,
181
+ {
182
+ hostProps : {
183
+ onChange : onChange
184
+ }
185
+ }
186
+ ) ;
187
+ spectator . tick ( ) ; // Needs to tick to interact with select which is async
188
+ expect ( onChange ) . not . toHaveBeenCalled ( ) ;
189
+ spectator . click ( spectator . query ( byText ( 'None' ) ) ! ) ;
190
+ const options = spectator . queryAll ( '.select-option' , { root : true } ) ;
191
+ spectator . click ( options [ 3 ] ) ;
192
+ // Wait for debounce
193
+ spectator . tick ( 500 ) ;
194
+ // Should not emit on switching to map group by, not eligible without a subpath
195
+ expect ( onChange ) . not . toHaveBeenCalled ( ) ;
196
+ spectator . typeInElement ( 'test.subpath' , '.group-by-path-input input' ) ;
197
+ expect ( onChange ) . not . toHaveBeenCalled ( ) ;
198
+ // Wait for debounce
199
+ spectator . tick ( 500 ) ;
200
+ expect ( onChange ) . toHaveBeenCalledWith ( { key : 'test map' , subpath : 'test.subpath' } ) ;
111
201
flush ( ) ; // Overlay removes async
112
202
} ) ) ;
113
203
} ) ;
0 commit comments