traceView.spec.tsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. import {initializeData as _initializeData} from 'sentry-test/performance/initializePerformanceData';
  2. import {
  3. act,
  4. render,
  5. screen,
  6. userEvent,
  7. waitFor,
  8. within,
  9. } from 'sentry-test/reactTestingLibrary';
  10. import * as AnchorLinkManager from 'sentry/components/events/interfaces/spans/anchorLinkManager';
  11. import TraceView from 'sentry/components/events/interfaces/spans/traceView';
  12. import {spanTargetHash} from 'sentry/components/events/interfaces/spans/utils';
  13. import WaterfallModel from 'sentry/components/events/interfaces/spans/waterfallModel';
  14. import ProjectsStore from 'sentry/stores/projectsStore';
  15. import {EntryType, EventTransaction} from 'sentry/types';
  16. import {QuickTraceContext} from 'sentry/utils/performance/quickTrace/quickTraceContext';
  17. import QuickTraceQuery from 'sentry/utils/performance/quickTrace/quickTraceQuery';
  18. function initializeData(settings) {
  19. const data = _initializeData(settings);
  20. act(() => void ProjectsStore.loadInitialData(data.organization.projects));
  21. return data;
  22. }
  23. function generateSampleEvent(): EventTransaction {
  24. const event = {
  25. id: '2b658a829a21496b87fd1f14a61abf65',
  26. eventID: '2b658a829a21496b87fd1f14a61abf65',
  27. title: '/organizations/:orgId/discover/results/',
  28. type: 'transaction',
  29. startTimestamp: 1622079935.86141,
  30. endTimestamp: 1622079940.032905,
  31. contexts: {
  32. trace: {
  33. trace_id: '8cbbc19c0f54447ab702f00263262726',
  34. span_id: 'a000000000000000',
  35. op: 'pageload',
  36. status: 'unknown',
  37. type: 'trace',
  38. },
  39. },
  40. entries: [
  41. {
  42. data: [],
  43. type: EntryType.SPANS,
  44. },
  45. ],
  46. } as EventTransaction;
  47. return event;
  48. }
  49. function generateSampleSpan(
  50. description: string | null,
  51. op: string | null,
  52. span_id: string,
  53. parent_span_id: string,
  54. event: EventTransaction
  55. ) {
  56. const span = {
  57. start_timestamp: 1000,
  58. timestamp: 2000,
  59. description,
  60. op,
  61. span_id,
  62. parent_span_id,
  63. trace_id: '8cbbc19c0f54447ab702f00263262726',
  64. status: 'ok',
  65. tags: {
  66. 'http.status_code': '200',
  67. },
  68. data: {},
  69. };
  70. event.entries[0].data.push(span);
  71. return span;
  72. }
  73. describe('TraceView', () => {
  74. afterEach(() => {
  75. MockApiClient.clearMockResponses();
  76. });
  77. describe('Autogrouped spans tests', () => {
  78. it('should render siblings with the same op and description as a grouped span in the minimap and span tree', async () => {
  79. const data = initializeData({
  80. features: ['performance-autogroup-sibling-spans'],
  81. });
  82. const event = generateSampleEvent();
  83. generateSampleSpan(
  84. 'group me',
  85. 'http',
  86. 'b000000000000000',
  87. 'a000000000000000',
  88. event
  89. );
  90. generateSampleSpan(
  91. 'group me',
  92. 'http',
  93. 'c000000000000000',
  94. 'a000000000000000',
  95. event
  96. );
  97. generateSampleSpan(
  98. 'group me',
  99. 'http',
  100. 'd000000000000000',
  101. 'a000000000000000',
  102. event
  103. );
  104. generateSampleSpan(
  105. 'group me',
  106. 'http',
  107. 'e000000000000000',
  108. 'a000000000000000',
  109. event
  110. );
  111. generateSampleSpan(
  112. 'group me',
  113. 'http',
  114. 'f000000000000000',
  115. 'a000000000000000',
  116. event
  117. );
  118. const waterfallModel = new WaterfallModel(event);
  119. render(
  120. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  121. );
  122. expect(await screen.findByTestId('minimap-sibling-group-bar')).toBeInTheDocument();
  123. expect(await screen.findByTestId('span-row-2')).toHaveTextContent('Autogrouped');
  124. expect(screen.queryByTestId('span-row-3')).not.toBeInTheDocument();
  125. });
  126. it('should expand grouped siblings when clicked, and then regroup when clicked again', async () => {
  127. // eslint-disable-next-line no-console
  128. jest.spyOn(console, 'error').mockImplementation(jest.fn());
  129. const data = initializeData({
  130. features: ['performance-autogroup-sibling-spans'],
  131. });
  132. const event = generateSampleEvent();
  133. generateSampleSpan(
  134. 'group me',
  135. 'http',
  136. 'b000000000000000',
  137. 'a000000000000000',
  138. event
  139. );
  140. generateSampleSpan(
  141. 'group me',
  142. 'http',
  143. 'c000000000000000',
  144. 'a000000000000000',
  145. event
  146. );
  147. generateSampleSpan(
  148. 'group me',
  149. 'http',
  150. 'd000000000000000',
  151. 'a000000000000000',
  152. event
  153. );
  154. generateSampleSpan(
  155. 'group me',
  156. 'http',
  157. 'e000000000000000',
  158. 'a000000000000000',
  159. event
  160. );
  161. generateSampleSpan(
  162. 'group me',
  163. 'http',
  164. 'f000000000000000',
  165. 'a000000000000000',
  166. event
  167. );
  168. const waterfallModel = new WaterfallModel(event);
  169. render(
  170. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  171. );
  172. const groupedSiblingsSpan = await screen.findByText('Autogrouped — http —');
  173. userEvent.click(groupedSiblingsSpan);
  174. await waitFor(() =>
  175. expect(screen.queryByText('Autogrouped — http —')).not.toBeInTheDocument()
  176. );
  177. for (let i = 1; i < 7; i++) {
  178. expect(await screen.findByTestId(`span-row-${i}`)).toBeInTheDocument();
  179. }
  180. const regroupButton = await screen.findByText('Regroup');
  181. expect(regroupButton).toBeInTheDocument();
  182. userEvent.click(regroupButton);
  183. await waitFor(() =>
  184. expect(screen.queryByTestId('span-row-6')).not.toBeInTheDocument()
  185. );
  186. expect(await screen.findByText('Autogrouped — http —')).toBeInTheDocument();
  187. });
  188. it("should not group sibling spans that don't have the same op or description", async () => {
  189. const data = initializeData({
  190. features: ['performance-autogroup-sibling-spans'],
  191. });
  192. const event = generateSampleEvent();
  193. generateSampleSpan('test', 'http', 'b000000000000000', 'a000000000000000', event);
  194. generateSampleSpan(
  195. 'group me',
  196. 'http',
  197. 'c000000000000000',
  198. 'a000000000000000',
  199. event
  200. );
  201. generateSampleSpan(
  202. 'group me',
  203. 'http',
  204. 'd000000000000000',
  205. 'a000000000000000',
  206. event
  207. );
  208. generateSampleSpan(
  209. 'group me',
  210. 'http',
  211. 'e000000000000000',
  212. 'a000000000000000',
  213. event
  214. );
  215. generateSampleSpan(
  216. 'group me',
  217. 'http',
  218. 'f000000000000000',
  219. 'a000000000000000',
  220. event
  221. );
  222. generateSampleSpan(
  223. 'group me',
  224. 'http',
  225. 'ff00000000000000',
  226. 'a000000000000000',
  227. event
  228. );
  229. generateSampleSpan('test', 'http', 'fff0000000000000', 'a000000000000000', event);
  230. const waterfallModel = new WaterfallModel(event);
  231. render(
  232. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  233. );
  234. expect(await screen.findByText('group me')).toBeInTheDocument();
  235. expect(await screen.findAllByText('test')).toHaveLength(2);
  236. });
  237. it('should autogroup similar nested spans', async () => {
  238. const data = initializeData({});
  239. const event = generateSampleEvent();
  240. generateSampleSpan(
  241. 'group me',
  242. 'http',
  243. 'b000000000000000',
  244. 'a000000000000000',
  245. event
  246. );
  247. generateSampleSpan(
  248. 'group me',
  249. 'http',
  250. 'c000000000000000',
  251. 'b000000000000000',
  252. event
  253. );
  254. generateSampleSpan(
  255. 'group me',
  256. 'http',
  257. 'd000000000000000',
  258. 'c000000000000000',
  259. event
  260. );
  261. generateSampleSpan(
  262. 'group me',
  263. 'http',
  264. 'e000000000000000',
  265. 'd000000000000000',
  266. event
  267. );
  268. generateSampleSpan(
  269. 'group me',
  270. 'http',
  271. 'f000000000000000',
  272. 'e000000000000000',
  273. event
  274. );
  275. const waterfallModel = new WaterfallModel(event);
  276. render(
  277. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  278. );
  279. const grouped = await screen.findByText('group me');
  280. expect(grouped).toBeInTheDocument();
  281. });
  282. it('should expand/collapse only the sibling group that is clicked, even if multiple groups have the same op and description', async () => {
  283. const data = initializeData({features: ['performance-autogroup-sibling-spans']});
  284. const event = generateSampleEvent();
  285. generateSampleSpan(
  286. 'group me',
  287. 'http',
  288. 'b000000000000000',
  289. 'a000000000000000',
  290. event
  291. );
  292. generateSampleSpan(
  293. 'group me',
  294. 'http',
  295. 'c000000000000000',
  296. 'a000000000000000',
  297. event
  298. );
  299. generateSampleSpan(
  300. 'group me',
  301. 'http',
  302. 'd000000000000000',
  303. 'a000000000000000',
  304. event
  305. );
  306. generateSampleSpan(
  307. 'group me',
  308. 'http',
  309. 'e000000000000000',
  310. 'a000000000000000',
  311. event
  312. );
  313. generateSampleSpan(
  314. 'group me',
  315. 'http',
  316. 'f000000000000000',
  317. 'a000000000000000',
  318. event
  319. );
  320. generateSampleSpan('not me', 'http', 'aa00000000000000', 'a000000000000000', event);
  321. generateSampleSpan(
  322. 'group me',
  323. 'http',
  324. 'bb00000000000000',
  325. 'a000000000000000',
  326. event
  327. );
  328. generateSampleSpan(
  329. 'group me',
  330. 'http',
  331. 'cc00000000000000',
  332. 'a000000000000000',
  333. event
  334. );
  335. generateSampleSpan(
  336. 'group me',
  337. 'http',
  338. 'dd00000000000000',
  339. 'a000000000000000',
  340. event
  341. );
  342. generateSampleSpan(
  343. 'group me',
  344. 'http',
  345. 'ee00000000000000',
  346. 'a000000000000000',
  347. event
  348. );
  349. generateSampleSpan(
  350. 'group me',
  351. 'http',
  352. 'ff00000000000000',
  353. 'a000000000000000',
  354. event
  355. );
  356. const waterfallModel = new WaterfallModel(event);
  357. render(
  358. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  359. );
  360. expect(screen.queryAllByText('group me')).toHaveLength(2);
  361. const firstGroup = screen.queryAllByText('Autogrouped — http —')[0];
  362. userEvent.click(firstGroup);
  363. expect(await screen.findAllByText('group me')).toHaveLength(6);
  364. const secondGroup = await screen.findByText('Autogrouped — http —');
  365. userEvent.click(secondGroup);
  366. expect(await screen.findAllByText('group me')).toHaveLength(10);
  367. const firstRegroup = screen.queryAllByText('Regroup')[0];
  368. userEvent.click(firstRegroup);
  369. expect(await screen.findAllByText('group me')).toHaveLength(6);
  370. const secondRegroup = await screen.findByText('Regroup');
  371. userEvent.click(secondRegroup);
  372. expect(await screen.findAllByText('group me')).toHaveLength(2);
  373. });
  374. it('should allow expanding of embedded transactions', async () => {
  375. const {organization, project, location} = initializeData({
  376. features: ['unified-span-view'],
  377. });
  378. const event = generateSampleEvent();
  379. generateSampleSpan(
  380. 'parent span',
  381. 'db',
  382. 'b000000000000000',
  383. 'a000000000000000',
  384. event
  385. );
  386. const waterfallModel = new WaterfallModel(event);
  387. const eventsTraceMock = MockApiClient.addMockResponse({
  388. url: `/organizations/${organization.slug}/events-trace/${event.contexts.trace?.trace_id}/`,
  389. method: 'GET',
  390. statusCode: 200,
  391. body: [
  392. event,
  393. {
  394. errors: [],
  395. event_id: '998d7e2c304c45729545e4434e2967cb',
  396. generation: 1,
  397. parent_event_id: '2b658a829a21496b87fd1f14a61abf65',
  398. parent_span_id: 'b000000000000000',
  399. project_id: project.id,
  400. project_slug: project.slug,
  401. span_id: '8596e2795f88471d',
  402. transaction:
  403. '/api/0/organizations/{organization_slug}/events/{project_slug}:{event_id}/',
  404. 'transaction.duration': 159,
  405. 'transaction.op': 'http.server',
  406. },
  407. ],
  408. });
  409. const eventsTraceLightMock = MockApiClient.addMockResponse({
  410. url: `/organizations/${organization.slug}/events-trace-light/${event.contexts.trace?.trace_id}/`,
  411. method: 'GET',
  412. statusCode: 200,
  413. body: [
  414. event,
  415. {
  416. errors: [],
  417. event_id: '998d7e2c304c45729545e4434e2967cb',
  418. generation: 1,
  419. parent_event_id: '2b658a829a21496b87fd1f14a61abf65',
  420. parent_span_id: 'b000000000000000',
  421. project_id: project.id,
  422. project_slug: project.slug,
  423. span_id: '8596e2795f88471d',
  424. transaction:
  425. '/api/0/organizations/{organization_slug}/events/{project_slug}:{event_id}/',
  426. 'transaction.duration': 159,
  427. 'transaction.op': 'http.server',
  428. },
  429. ],
  430. });
  431. const embeddedEvent = {
  432. ...generateSampleEvent(),
  433. id: '998d7e2c304c45729545e4434e2967cb',
  434. eventID: '998d7e2c304c45729545e4434e2967cb',
  435. };
  436. embeddedEvent.contexts.trace!.span_id = 'a111111111111111';
  437. const embeddedSpan = generateSampleSpan(
  438. 'i am embedded :)',
  439. 'test',
  440. 'b111111111111111',
  441. 'b000000000000000',
  442. embeddedEvent
  443. );
  444. embeddedSpan.trace_id = '8cbbc19c0f54447ab702f00263262726';
  445. const fetchEmbeddedTransactionMock = MockApiClient.addMockResponse({
  446. url: `/organizations/${organization.slug}/events/${project.slug}:998d7e2c304c45729545e4434e2967cb/`,
  447. method: 'GET',
  448. statusCode: 200,
  449. body: embeddedEvent,
  450. });
  451. render(
  452. <QuickTraceQuery event={event} location={location} orgSlug={organization.slug}>
  453. {results => (
  454. <QuickTraceContext.Provider value={results}>
  455. <TraceView organization={organization} waterfallModel={waterfallModel} />
  456. </QuickTraceContext.Provider>
  457. )}
  458. </QuickTraceQuery>
  459. );
  460. expect(eventsTraceMock).toHaveBeenCalled();
  461. expect(eventsTraceLightMock).toHaveBeenCalled();
  462. const embeddedTransactionBadge = await screen.findByTestId(
  463. 'embedded-transaction-badge'
  464. );
  465. expect(embeddedTransactionBadge).toBeInTheDocument();
  466. userEvent.click(embeddedTransactionBadge);
  467. expect(fetchEmbeddedTransactionMock).toHaveBeenCalled();
  468. expect(await screen.findByText(/i am embedded :\)/i)).toBeInTheDocument();
  469. });
  470. it('should correctly render sibling autogroup text when op and/or description is not provided', async () => {
  471. const data = initializeData({
  472. features: ['performance-autogroup-sibling-spans'],
  473. });
  474. const event1 = generateSampleEvent();
  475. generateSampleSpan(
  476. 'group me',
  477. null,
  478. 'b000000000000000',
  479. 'a000000000000000',
  480. event1
  481. );
  482. generateSampleSpan(
  483. 'group me',
  484. null,
  485. 'c000000000000000',
  486. 'a000000000000000',
  487. event1
  488. );
  489. generateSampleSpan(
  490. 'group me',
  491. null,
  492. 'd000000000000000',
  493. 'a000000000000000',
  494. event1
  495. );
  496. generateSampleSpan(
  497. 'group me',
  498. null,
  499. 'e000000000000000',
  500. 'a000000000000000',
  501. event1
  502. );
  503. generateSampleSpan(
  504. 'group me',
  505. null,
  506. 'f000000000000000',
  507. 'a000000000000000',
  508. event1
  509. );
  510. const {rerender} = render(
  511. <TraceView
  512. organization={data.organization}
  513. waterfallModel={new WaterfallModel(event1)}
  514. />
  515. );
  516. expect(await screen.findByTestId('span-row-2')).toHaveTextContent(
  517. /Autogrouped — group me/
  518. );
  519. const event2 = generateSampleEvent();
  520. generateSampleSpan(null, 'http', 'b000000000000000', 'a000000000000000', event2);
  521. generateSampleSpan(null, 'http', 'c000000000000000', 'a000000000000000', event2);
  522. generateSampleSpan(null, 'http', 'd000000000000000', 'a000000000000000', event2);
  523. generateSampleSpan(null, 'http', 'e000000000000000', 'a000000000000000', event2);
  524. generateSampleSpan(null, 'http', 'f000000000000000', 'a000000000000000', event2);
  525. rerender(
  526. <TraceView
  527. organization={data.organization}
  528. waterfallModel={new WaterfallModel(event2)}
  529. />
  530. );
  531. expect(await screen.findByTestId('span-row-2')).toHaveTextContent(
  532. /Autogrouped — http/
  533. );
  534. const event3 = generateSampleEvent();
  535. generateSampleSpan(null, null, 'b000000000000000', 'a000000000000000', event3);
  536. generateSampleSpan(null, null, 'c000000000000000', 'a000000000000000', event3);
  537. generateSampleSpan(null, null, 'd000000000000000', 'a000000000000000', event3);
  538. generateSampleSpan(null, null, 'e000000000000000', 'a000000000000000', event3);
  539. generateSampleSpan(null, null, 'f000000000000000', 'a000000000000000', event3);
  540. rerender(
  541. <TraceView
  542. organization={data.organization}
  543. waterfallModel={new WaterfallModel(event3)}
  544. />
  545. );
  546. expect(await screen.findByTestId('span-row-2')).toHaveTextContent(
  547. /Autogrouped — siblings/
  548. );
  549. });
  550. it('should automatically expand a sibling span group and select a span if it is anchored', async () => {
  551. const data = initializeData({
  552. features: ['performance-autogroup-sibling-spans'],
  553. });
  554. const event = generateSampleEvent();
  555. generateSampleSpan(
  556. 'group me',
  557. 'http',
  558. 'b000000000000000',
  559. 'a000000000000000',
  560. event
  561. );
  562. generateSampleSpan(
  563. 'group me',
  564. 'http',
  565. 'c000000000000000',
  566. 'a000000000000000',
  567. event
  568. );
  569. generateSampleSpan(
  570. 'group me',
  571. 'http',
  572. 'd000000000000000',
  573. 'a000000000000000',
  574. event
  575. );
  576. generateSampleSpan(
  577. 'group me',
  578. 'http',
  579. 'e000000000000000',
  580. 'a000000000000000',
  581. event
  582. );
  583. generateSampleSpan(
  584. 'group me',
  585. 'http',
  586. 'f000000000000000',
  587. 'a000000000000000',
  588. event
  589. );
  590. // Manually set the hash here, the AnchorLinkManager is expected to automatically expand the group and scroll to the span with this id
  591. location.hash = spanTargetHash('c000000000000000');
  592. const waterfallModel = new WaterfallModel(event);
  593. render(
  594. <AnchorLinkManager.Provider>
  595. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  596. </AnchorLinkManager.Provider>
  597. );
  598. expect(await screen.findByText(/c000000000000000/i)).toBeInTheDocument();
  599. location.hash = '';
  600. });
  601. it('should automatically expand a descendant span group and select a span if it is anchored', async () => {
  602. const data = initializeData({});
  603. const event = generateSampleEvent();
  604. generateSampleSpan(
  605. 'group me',
  606. 'http',
  607. 'b000000000000000',
  608. 'a000000000000000',
  609. event
  610. );
  611. generateSampleSpan(
  612. 'group me',
  613. 'http',
  614. 'c000000000000000',
  615. 'b000000000000000',
  616. event
  617. );
  618. generateSampleSpan(
  619. 'group me',
  620. 'http',
  621. 'd000000000000000',
  622. 'c000000000000000',
  623. event
  624. );
  625. generateSampleSpan(
  626. 'group me',
  627. 'http',
  628. 'e000000000000000',
  629. 'd000000000000000',
  630. event
  631. );
  632. generateSampleSpan(
  633. 'group me',
  634. 'http',
  635. 'f000000000000000',
  636. 'e000000000000000',
  637. event
  638. );
  639. location.hash = spanTargetHash('d000000000000000');
  640. const waterfallModel = new WaterfallModel(event);
  641. render(
  642. <AnchorLinkManager.Provider>
  643. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  644. </AnchorLinkManager.Provider>
  645. );
  646. expect(await screen.findByText(/d000000000000000/i)).toBeInTheDocument();
  647. location.hash = '';
  648. });
  649. });
  650. it('should merge web vitals labels if they are too close together', () => {
  651. const data = initializeData({});
  652. const event = generateSampleEvent();
  653. generateSampleSpan('browser', 'test1', 'b000000000000000', 'a000000000000000', event);
  654. generateSampleSpan('browser', 'test2', 'c000000000000000', 'a000000000000000', event);
  655. generateSampleSpan('browser', 'test3', 'd000000000000000', 'a000000000000000', event);
  656. generateSampleSpan('browser', 'test4', 'e000000000000000', 'a000000000000000', event);
  657. generateSampleSpan('browser', 'test5', 'f000000000000000', 'a000000000000000', event);
  658. event.measurements = {
  659. fcp: {value: 1000},
  660. fp: {value: 1050},
  661. lcp: {value: 1100},
  662. };
  663. const waterfallModel = new WaterfallModel(event);
  664. render(
  665. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  666. );
  667. const labelContainer = screen.getByText(/fcp/i).parentElement?.parentElement;
  668. expect(labelContainer).toBeInTheDocument();
  669. expect(within(labelContainer!).getByText(/fcp/i)).toBeInTheDocument();
  670. expect(within(labelContainer!).getByText(/fp/i)).toBeInTheDocument();
  671. expect(within(labelContainer!).getByText(/lcp/i)).toBeInTheDocument();
  672. });
  673. it('should not merge web vitals labels if they are spaced away from each other', () => {
  674. const data = initializeData({});
  675. const event = generateSampleEvent();
  676. generateSampleSpan('browser', 'test1', 'b000000000000000', 'a000000000000000', event);
  677. event.startTimestamp = 1;
  678. event.endTimestamp = 100;
  679. event.measurements = {
  680. fcp: {value: 858.3002090454102, unit: 'millisecond'},
  681. lcp: {value: 1000363.800048828125, unit: 'millisecond'},
  682. };
  683. const waterfallModel = new WaterfallModel(event);
  684. render(
  685. <TraceView organization={data.organization} waterfallModel={waterfallModel} />
  686. );
  687. const fcpLabelContainer = screen.getByText(/fcp/i).parentElement?.parentElement;
  688. expect(fcpLabelContainer).toBeInTheDocument();
  689. // LCP should not be merged along with FCP. We expect it to be in a separate element
  690. expect(within(fcpLabelContainer!).queryByText(/lcp/i)).not.toBeInTheDocument();
  691. const lcpLabelContainer = screen.getByText(/lcp/i).parentElement?.parentElement;
  692. expect(lcpLabelContainer).toBeInTheDocument();
  693. });
  694. });