Skip to content

Commit 7d243b2

Browse files
authored
feat(traces): Add cross event dropdown functionality (#104100)
This PR adds in some refinements to the cross event dropdown, such as proper labels, ability to add a second cross event, and disabling itself when there are two cross events present. I also moved the search section of the spans tab into its own file to keep things a bit more tidy, as well as refactoring the spans tab tests to use the `additionalWrapper` arg, over wrapping in the wrapper saving a couple lines. Ticket: EXP-618
1 parent 81497aa commit 7d243b2

File tree

3 files changed

+367
-298
lines changed

3 files changed

+367
-298
lines changed

static/app/views/explore/spans/spansTab.spec.tsx

Lines changed: 106 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ describe('SpansTabContent', () => {
6666
'gen-ai-explore-traces',
6767
'gen-ai-explore-traces-consent-ui',
6868
'search-query-builder-case-insensitivity',
69+
'traces-page-cross-event-querying',
6970
],
7071
},
7172
});
@@ -142,12 +143,10 @@ describe('SpansTabContent', () => {
142143
});
143144

144145
it('should fire analytics once per change', async () => {
145-
render(
146-
<Wrapper>
147-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
148-
</Wrapper>,
149-
{organization}
150-
);
146+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
147+
organization,
148+
additionalWrapper: Wrapper,
149+
});
151150

152151
await screen.findByText(/No spans found/);
153152
expect(trackAnalytics).toHaveBeenCalledTimes(1);
@@ -186,12 +185,7 @@ describe('SpansTabContent', () => {
186185
return <SpansTabContent datePageFilterProps={datePageFilterProps} />;
187186
}
188187

189-
render(
190-
<Wrapper>
191-
<Component />
192-
</Wrapper>,
193-
{organization}
194-
);
188+
render(<Component />, {organization, additionalWrapper: Wrapper});
195189

196190
const samples = screen.getByRole('tab', {name: 'Span Samples'});
197191
const aggregates = screen.getByRole('tab', {name: 'Aggregates'});
@@ -232,12 +226,10 @@ describe('SpansTabContent', () => {
232226
}, 20_000);
233227

234228
it('opens toolbar when switching to aggregates tab', async () => {
235-
render(
236-
<Wrapper>
237-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
238-
</Wrapper>,
239-
{organization}
240-
);
229+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
230+
organization,
231+
additionalWrapper: Wrapper,
232+
});
241233

242234
// by default the toolbar should be visible
243235
expect(screen.getByTestId('explore-span-toolbar')).toBeInTheDocument();
@@ -271,12 +263,10 @@ describe('SpansTabContent', () => {
271263

272264
describe('case sensitivity', () => {
273265
it('renders the case sensitivity toggle', () => {
274-
render(
275-
<Wrapper>
276-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
277-
</Wrapper>,
278-
{organization}
279-
);
266+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
267+
organization,
268+
additionalWrapper: Wrapper,
269+
});
280270

281271
const caseSensitivityToggle = screen.getByRole('button', {
282272
name: 'Ignore case',
@@ -286,10 +276,8 @@ describe('SpansTabContent', () => {
286276

287277
it('toggles case sensitivity', async () => {
288278
const {router} = render(
289-
<Wrapper>
290-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
291-
</Wrapper>,
292-
{organization}
279+
<SpansTabContent datePageFilterProps={datePageFilterProps} />,
280+
{organization, additionalWrapper: Wrapper}
293281
);
294282

295283
const caseSensitivityToggle = screen.getByRole('button', {
@@ -314,12 +302,10 @@ describe('SpansTabContent', () => {
314302
body: {},
315303
});
316304

317-
render(
318-
<Wrapper>
319-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
320-
</Wrapper>,
321-
{organization}
322-
);
305+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
306+
organization,
307+
additionalWrapper: Wrapper,
308+
});
323309

324310
const caseSensitivityToggle = screen.getByRole('button', {
325311
name: 'Ignore case',
@@ -408,14 +394,10 @@ describe('SpansTabContent', () => {
408394
});
409395

410396
it('should show hints', () => {
411-
render(
412-
<Wrapper>
413-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
414-
</Wrapper>,
415-
{
416-
organization,
417-
}
418-
);
397+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
398+
organization,
399+
additionalWrapper: Wrapper,
400+
});
419401

420402
expect(screen.getByText('stringTag1')).toBeInTheDocument();
421403
expect(screen.getByText('stringTag2')).toBeInTheDocument();
@@ -440,12 +422,10 @@ describe('SpansTabContent', () => {
440422

441423
describe('when the AI features are disabled', () => {
442424
it('does not display the Ask Seer combobox', async () => {
443-
render(
444-
<Wrapper>
445-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
446-
</Wrapper>,
447-
{organization: {...organization, features: []}}
448-
);
425+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
426+
organization: {...organization, features: []},
427+
additionalWrapper: Wrapper,
428+
});
449429

450430
const input = screen.getByRole('combobox');
451431
await userEvent.click(input);
@@ -455,12 +435,10 @@ describe('SpansTabContent', () => {
455435
});
456436

457437
it('brings along the query', async () => {
458-
render(
459-
<Wrapper>
460-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
461-
</Wrapper>,
462-
{organization}
463-
);
438+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
439+
organization,
440+
additionalWrapper: Wrapper,
441+
});
464442

465443
const input = screen.getByRole('combobox');
466444
await userEvent.click(input);
@@ -481,12 +459,10 @@ describe('SpansTabContent', () => {
481459
});
482460

483461
it('brings along the user input', async () => {
484-
render(
485-
<Wrapper>
486-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
487-
</Wrapper>,
488-
{organization}
489-
);
462+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
463+
organization,
464+
additionalWrapper: Wrapper,
465+
});
490466

491467
const input = screen.getByRole('combobox');
492468
await userEvent.click(input);
@@ -505,12 +481,10 @@ describe('SpansTabContent', () => {
505481
});
506482

507483
it('brings along only the query and the user input', async () => {
508-
render(
509-
<Wrapper>
510-
<SpansTabContent datePageFilterProps={datePageFilterProps} />
511-
</Wrapper>,
512-
{organization}
513-
);
484+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
485+
organization,
486+
additionalWrapper: Wrapper,
487+
});
514488

515489
const input = screen.getByRole('combobox');
516490
await userEvent.click(input);
@@ -529,4 +503,70 @@ describe('SpansTabContent', () => {
529503
});
530504
});
531505
});
506+
507+
describe('cross events', () => {
508+
it('displays the cross events dropdown', async () => {
509+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
510+
organization,
511+
additionalWrapper: Wrapper,
512+
});
513+
514+
expect(
515+
screen.getByRole('button', {name: 'Add a cross event query'})
516+
).toBeInTheDocument();
517+
518+
await userEvent.click(
519+
screen.getByRole('button', {name: 'Add a cross event query'})
520+
);
521+
522+
expect(screen.getByRole('menuitemradio', {name: 'Spans'})).toBeInTheDocument();
523+
expect(screen.getByRole('menuitemradio', {name: 'Logs'})).toBeInTheDocument();
524+
expect(screen.getByRole('menuitemradio', {name: 'Metrics'})).toBeInTheDocument();
525+
});
526+
527+
it('adds a cross event query', async () => {
528+
const {router} = render(
529+
<SpansTabContent datePageFilterProps={datePageFilterProps} />,
530+
{organization, additionalWrapper: Wrapper}
531+
);
532+
533+
await userEvent.click(
534+
screen.getByRole('button', {name: 'Add a cross event query'})
535+
);
536+
537+
expect(screen.getByRole('menuitemradio', {name: 'Spans'})).toBeInTheDocument();
538+
await userEvent.click(screen.getByRole('menuitemradio', {name: 'Spans'}));
539+
540+
await waitFor(() =>
541+
expect(router.location.query.crossEvents).toEqual(
542+
JSON.stringify([{query: '', type: 'spans'}])
543+
)
544+
);
545+
});
546+
547+
it('disables dropdown when there are 2 cross events', () => {
548+
render(<SpansTabContent datePageFilterProps={datePageFilterProps} />, {
549+
organization,
550+
additionalWrapper: Wrapper,
551+
initialRouterConfig: {
552+
location: {
553+
pathname: '/organizations/org-slug/explore/traces/',
554+
query: {
555+
crossEvents: JSON.stringify([
556+
{query: '', type: 'spans'},
557+
{query: '', type: 'logs'},
558+
]),
559+
},
560+
},
561+
},
562+
});
563+
564+
expect(
565+
screen.getByRole('button', {name: 'Add a cross event query'})
566+
).toBeInTheDocument();
567+
expect(
568+
screen.getByRole('button', {name: 'Add a cross event query'})
569+
).toBeDisabled();
570+
});
571+
});
532572
});

0 commit comments

Comments
 (0)