11import { OrganizationFixture } from 'sentry-fixture/organization' ;
22
3- import { act , renderHookWithProviders , waitFor } from 'sentry-test/reactTestingLibrary' ;
3+ import { renderHookWithProviders , waitFor } from 'sentry-test/reactTestingLibrary' ;
44
5- import { parseSearch } from 'sentry/components/searchSyntax/parser' ;
65import {
7- extractFilterKeys ,
86 useAttributeValidation ,
97 type AttributeValidationSelection ,
108} from 'sentry/views/explore/hooks/useAttributeValidation' ;
@@ -16,69 +14,31 @@ const DEFAULT_SELECTION: AttributeValidationSelection = {
1614 projects : [ ] ,
1715} ;
1816
19- describe ( 'extractFilterKeys' , ( ) => {
20- it ( 'returns empty array for null parsedQuery' , ( ) => {
21- expect ( extractFilterKeys ( null ) ) . toEqual ( [ ] ) ;
22- } ) ;
23-
24- it ( 'returns empty array for empty parsedQuery' , ( ) => {
25- expect ( extractFilterKeys ( parseSearch ( '' ) ) ) . toEqual ( [ ] ) ;
26- } ) ;
27-
28- it ( 'returns empty array when there are no filter tokens' , ( ) => {
29- expect ( extractFilterKeys ( parseSearch ( 'hello world' ) ) ) . toEqual ( [ ] ) ;
30- } ) ;
31-
32- it ( 'extracts and sorts filter keys' , ( ) => {
33- expect ( extractFilterKeys ( parseSearch ( 'zebra:value apple:value' ) ) ) . toEqual ( [
34- 'apple' ,
35- 'zebra' ,
36- ] ) ;
37- } ) ;
38-
39- it ( 'deduplicates keys' , ( ) => {
40- expect ( extractFilterKeys ( parseSearch ( 'duplicate:value duplicate:other' ) ) ) . toEqual ( [
41- 'duplicate' ,
42- ] ) ;
43- } ) ;
44-
45- it ( 'returns stable reference for empty results' , ( ) => {
46- const result1 = extractFilterKeys ( null ) ;
47- const result2 = extractFilterKeys ( null ) ;
48- expect ( result1 ) . toBe ( result2 ) ;
49- } ) ;
50- } ) ;
51-
5217describe ( 'useAttributeValidation' , ( ) => {
5318 const organization = OrganizationFixture ( { slug : ORG_SLUG } ) ;
5419
55- it ( 'returns empty invalidFilterKeys initially ' , ( ) => {
20+ it ( 'returns empty invalidFilterKeys for empty query ' , ( ) => {
5621 const { result} = renderHookWithProviders (
57- ( ) => useAttributeValidation ( TraceItemDataset . SPANS ) ,
22+ ( ) => useAttributeValidation ( TraceItemDataset . SPANS , '' , DEFAULT_SELECTION ) ,
5823 { organization}
5924 ) ;
6025
6126 expect ( result . current . invalidFilterKeys ) . toEqual ( [ ] ) ;
6227 } ) ;
6328
64- it ( 'does not call the API when query has no filter keys' , async ( ) => {
29+ it ( 'does not call the API when query has no filter keys' , ( ) => {
6530 const mockValidate = MockApiClient . addMockResponse ( {
6631 url : `/organizations/${ ORG_SLUG } /trace-items/attributes/validate/` ,
6732 method : 'POST' ,
6833 body : { attributes : { } } ,
6934 } ) ;
7035
71- const { result } = renderHookWithProviders (
72- ( ) => useAttributeValidation ( TraceItemDataset . SPANS ) ,
36+ renderHookWithProviders (
37+ ( ) => useAttributeValidation ( TraceItemDataset . SPANS , '' , DEFAULT_SELECTION ) ,
7338 { organization}
7439 ) ;
7540
76- await act ( async ( ) => {
77- await result . current . validateQuery ( '' , DEFAULT_SELECTION ) ;
78- } ) ;
79-
8041 expect ( mockValidate ) . not . toHaveBeenCalled ( ) ;
81- expect ( result . current . invalidFilterKeys ) . toEqual ( [ ] ) ;
8242 } ) ;
8343
8444 it ( 'sets invalidFilterKeys for keys the API reports as invalid' , async ( ) => {
@@ -94,17 +54,15 @@ describe('useAttributeValidation', () => {
9454 } ) ;
9555
9656 const { result} = renderHookWithProviders (
97- ( ) => useAttributeValidation ( TraceItemDataset . SPANS ) ,
57+ ( ) =>
58+ useAttributeValidation (
59+ TraceItemDataset . SPANS ,
60+ 'span.op:db unknown_key:value' ,
61+ DEFAULT_SELECTION
62+ ) ,
9863 { organization}
9964 ) ;
10065
101- await act ( async ( ) => {
102- await result . current . validateQuery (
103- 'span.op:db unknown_key:value' ,
104- DEFAULT_SELECTION
105- ) ;
106- } ) ;
107-
10866 await waitFor ( ( ) => {
10967 expect ( result . current . invalidFilterKeys ) . toEqual ( [ 'unknown_key' ] ) ;
11068 } ) ;
@@ -118,14 +76,11 @@ describe('useAttributeValidation', () => {
11876 } ) ;
11977
12078 const { result} = renderHookWithProviders (
121- ( ) => useAttributeValidation ( TraceItemDataset . SPANS ) ,
79+ ( ) =>
80+ useAttributeValidation ( TraceItemDataset . SPANS , 'span.op:db' , DEFAULT_SELECTION ) ,
12281 { organization}
12382 ) ;
12483
125- await act ( async ( ) => {
126- await result . current . validateQuery ( 'span.op:db' , DEFAULT_SELECTION ) ;
127- } ) ;
128-
12984 await waitFor ( ( ) => {
13085 expect ( result . current . invalidFilterKeys ) . toEqual ( [ ] ) ;
13186 } ) ;
@@ -138,17 +93,23 @@ describe('useAttributeValidation', () => {
13893 body : { attributes : { 'span.op' : { valid : true } } } ,
13994 } ) ;
14095
141- const { result} = renderHookWithProviders (
142- ( ) => useAttributeValidation ( TraceItemDataset . SPANS ) ,
143- { organization}
96+ const { result, rerender} = renderHookWithProviders (
97+ ( { query, selection} : { query : string ; selection : AttributeValidationSelection } ) =>
98+ useAttributeValidation ( TraceItemDataset . SPANS , query , selection ) ,
99+ {
100+ organization,
101+ initialProps : { query : 'span.op:db' , selection : DEFAULT_SELECTION } ,
102+ }
144103 ) ;
145104
146- await act ( async ( ) => {
147- await result . current . validateQuery ( 'span.op:db' , DEFAULT_SELECTION ) ;
105+ await waitFor ( ( ) => {
106+ expect ( result . current . invalidFilterKeys ) . toEqual ( [ ] ) ;
148107 } ) ;
149108
150- await act ( async ( ) => {
151- await result . current . validateQuery ( 'span.op:web' , DEFAULT_SELECTION ) ;
109+ rerender ( { query : 'span.op:web' , selection : DEFAULT_SELECTION } ) ;
110+
111+ await waitFor ( ( ) => {
112+ expect ( result . current . invalidFilterKeys ) . toEqual ( [ ] ) ;
152113 } ) ;
153114
154115 expect ( mockValidate ) . toHaveBeenCalledTimes ( 1 ) ;
@@ -161,22 +122,29 @@ describe('useAttributeValidation', () => {
161122 body : { attributes : { 'span.op' : { valid : true } } } ,
162123 } ) ;
163124
164- const { result} = renderHookWithProviders (
165- ( ) => useAttributeValidation ( TraceItemDataset . SPANS ) ,
166- { organization}
125+ const { result, rerender} = renderHookWithProviders (
126+ ( { query, selection} : { query : string ; selection : AttributeValidationSelection } ) =>
127+ useAttributeValidation ( TraceItemDataset . SPANS , query , selection ) ,
128+ {
129+ organization,
130+ initialProps : { query : 'span.op:db' , selection : DEFAULT_SELECTION } ,
131+ }
167132 ) ;
168133
169- await act ( async ( ) => {
170- await result . current . validateQuery ( 'span.op:db' , DEFAULT_SELECTION ) ;
134+ await waitFor ( ( ) => {
135+ expect ( result . current . invalidFilterKeys ) . toEqual ( [ ] ) ;
171136 } ) ;
172137
173- await act ( async ( ) => {
174- await result . current . validateQuery ( 'span.op:db' , {
138+ rerender ( {
139+ query : 'span.op:db' ,
140+ selection : {
175141 datetime : { period : '7d' , start : null , end : null , utc : false } ,
176142 projects : [ ] ,
177- } ) ;
143+ } ,
178144 } ) ;
179145
180- expect ( mockValidate ) . toHaveBeenCalledTimes ( 2 ) ;
146+ await waitFor ( ( ) => {
147+ expect ( mockValidate ) . toHaveBeenCalledTimes ( 2 ) ;
148+ } ) ;
181149 } ) ;
182150} ) ;
0 commit comments