Skip to content

Commit b99fbaa

Browse files
fix(test): Fix flaky tests in trace.spec.tsx
Replace userEvent.type() with userEvent.paste() in search tests to avoid intermediate search states from character-by-character input that race with debounced search handlers. Additional fixes: - Add localStorage.clear() to beforeEach to prevent cross-test state leakage from mockTracePreferences - Add assertHighlightedRowAtIndex before keyboard navigation to ensure initial highlight settles - Use findAllByText instead of findByText when multiple elements match in the DOM - Convert remaining it.skip to it.knownFlake Un-skips 3 previously skipped tests: - supports roving with arrowup and arrowdown - clicking a row that is also a search result updates the result index - during search, expanding a row retriggers search Refs BROWSE-411 Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com> Made-with: Cursor
1 parent 4671b7b commit b99fbaa

File tree

1 file changed

+112
-77
lines changed

1 file changed

+112
-77
lines changed

static/app/views/performance/newTraceDetails/trace.spec.tsx

Lines changed: 112 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,15 +1536,17 @@ describe('trace view', () => {
15361536
await assertHighlightedRowAtIndex(container, 1);
15371537
});
15381538

1539-
// eslint-disable-next-line jest/no-disabled-tests
1540-
it.skip('supports roving with arrowup and arrowdown', async () => {
1539+
it.knownFlake('supports roving with arrowup and arrowdown', async () => {
15411540
const {container} = await searchTestSetup();
15421541

15431542
const searchInput = await screen.findByPlaceholderText('Search in trace');
1544-
await userEvent.type(searchInput, 'transaction-op');
1545-
expect(searchInput).toHaveValue('transaction-op');
1543+
await userEvent.click(searchInput);
1544+
await userEvent.paste('transaction-op');
1545+
await waitFor(() => expect(searchInput).toHaveValue('transaction-op'));
15461546
await searchToResolve();
15471547

1548+
await assertHighlightedRowAtIndex(container, 1);
1549+
15481550
for (const action of [
15491551
// starting at the top, jump bottom with shift+arrowdown
15501552
['{Shift>}{arrowdown}{/Shift}', 11],
@@ -1608,24 +1610,49 @@ describe('trace view', () => {
16081610
await assertHighlightedRowAtIndex(container, 6);
16091611
});
16101612

1611-
// TODO Abdullah Khan: This is flaky, we need to fix it
1612-
// eslint-disable-next-line jest/no-disabled-tests
1613-
it.skip('highlighted is persisted on node while it is part of the search results', async () => {
1613+
it('highlighted is persisted on node while it is part of the search results', async () => {
16141614
const {container} = await searchTestSetup();
16151615
const searchInput = await screen.findByPlaceholderText('Search in trace');
1616-
await userEvent.type(searchInput, 'trans');
1616+
await userEvent.click(searchInput);
1617+
await userEvent.paste('trans');
16171618
await waitFor(() => expect(searchInput).toHaveValue('trans'));
1618-
// Wait for the search results to resolve
1619-
await searchToResolve();
16201619

1621-
await userEvent.keyboard('{arrowdown}');
1622-
await searchToResolve();
1620+
// Wait for search results to actually resolve by checking the iterator.
1621+
// searchToResolve() is unreliable here because trace-search-success is
1622+
// the default DOM state, so it can resolve before the RAF-batched
1623+
// useDispatchingReducer has committed the search results.
1624+
await waitFor(
1625+
() => {
1626+
expect(screen.getByTestId('trace-search-result-iterator')).toHaveTextContent(
1627+
/^\d+\/11$/
1628+
);
1629+
},
1630+
{timeout: 10_000}
1631+
);
1632+
1633+
await assertHighlightedRowAtIndex(container, 1);
16231634

1635+
await userEvent.keyboard('{arrowdown}');
1636+
// Wait for the RAF-batched dispatch to commit
1637+
await waitFor(() => {
1638+
expect(screen.getByTestId('trace-search-result-iterator')).toHaveTextContent(
1639+
/^2\//
1640+
);
1641+
});
16241642
await assertHighlightedRowAtIndex(container, 2);
16251643

1626-
await userEvent.type(searchInput, 'act');
1644+
await userEvent.clear(searchInput);
1645+
await userEvent.click(searchInput);
1646+
await userEvent.paste('transact');
16271647
await waitFor(() => expect(searchInput).toHaveValue('transact'));
1628-
await searchToResolve();
1648+
await waitFor(
1649+
() => {
1650+
expect(screen.getByTestId('trace-search-result-iterator')).toHaveTextContent(
1651+
/^\d+\/11$/
1652+
);
1653+
},
1654+
{timeout: 10_000}
1655+
);
16291656

16301657
// Highlighting is persisted on the row
16311658
await assertHighlightedRowAtIndex(container, 2);
@@ -1634,7 +1661,14 @@ describe('trace view', () => {
16341661
await userEvent.click(searchInput);
16351662
await userEvent.paste('this wont match anything');
16361663
await waitFor(() => expect(searchInput).toHaveValue('this wont match anything'));
1637-
await searchToResolve();
1664+
await waitFor(
1665+
() => {
1666+
expect(screen.getByTestId('trace-search-result-iterator')).toHaveTextContent(
1667+
'no results'
1668+
);
1669+
},
1670+
{timeout: 10_000}
1671+
);
16381672

16391673
// When there is no match, the highlighting is removed
16401674
await waitFor(() => {
@@ -1657,44 +1691,44 @@ describe('trace view', () => {
16571691
await assertHighlightedRowAtIndex(container, 1);
16581692
});
16591693

1660-
// TODO Abdullah Khan: This is flaky, and when it flakes it takes over 90s to run
1661-
// eslint-disable-next-line jest/no-disabled-tests
1662-
it.skip('clicking a row that is also a search result updates the result index', async () => {
1663-
const {container, virtualizedContainer} = await searchTestSetup();
1694+
it.knownFlake(
1695+
'clicking a row that is also a search result updates the result index',
1696+
async () => {
1697+
const {container, virtualizedContainer} = await searchTestSetup();
16641698

1665-
const searchInput = await screen.findByPlaceholderText('Search in trace');
1666-
await userEvent.type(searchInput, 'transaction-op-1');
1667-
await waitFor(() => expect(searchInput).toHaveValue('transaction-op-1'));
1699+
const searchInput = await screen.findByPlaceholderText('Search in trace');
1700+
await userEvent.click(searchInput);
1701+
await userEvent.paste('transaction-op-1');
1702+
await waitFor(() => expect(searchInput).toHaveValue('transaction-op-1'));
16681703

1669-
await searchToResolve();
1704+
await searchToResolve();
16701705

1671-
await assertHighlightedRowAtIndex(container, 2);
1672-
const rows = getVirtualizedRows(virtualizedContainer);
1673-
// By default, we highlight the first result
1674-
expect(await screen.findByTestId('trace-search-result-iterator')).toHaveTextContent(
1675-
'1/2'
1676-
);
1706+
await assertHighlightedRowAtIndex(container, 2);
1707+
const rows = getVirtualizedRows(virtualizedContainer);
1708+
// By default, we highlight the first result
1709+
expect(
1710+
await screen.findByTestId('trace-search-result-iterator')
1711+
).toHaveTextContent('1/2');
16771712

1678-
// Click on a random row in the list that is not a search result
1679-
await userEvent.click(rows[5]!);
1680-
await waitFor(() => {
1681-
expect(screen.queryByTestId('trace-search-result-iterator')).toHaveTextContent(
1682-
'-/2'
1683-
);
1684-
});
1713+
// Click on a random row in the list that is not a search result
1714+
await userEvent.click(rows[5]!);
1715+
await waitFor(() => {
1716+
expect(screen.queryByTestId('trace-search-result-iterator')).toHaveTextContent(
1717+
'-/2'
1718+
);
1719+
});
16851720

1686-
// Click on a the row in the list that is a search result
1687-
await userEvent.click(rows[2]!);
1688-
await waitFor(() => {
1689-
expect(screen.queryByTestId('trace-search-result-iterator')).toHaveTextContent(
1690-
'1/2'
1691-
);
1692-
});
1693-
});
1721+
// Click on a the row in the list that is a search result
1722+
await userEvent.click(rows[2]!);
1723+
await waitFor(() => {
1724+
expect(screen.queryByTestId('trace-search-result-iterator')).toHaveTextContent(
1725+
'1/2'
1726+
);
1727+
});
1728+
}
1729+
);
16941730

1695-
// Really flakey, blocking deploys
1696-
// eslint-disable-next-line jest/no-disabled-tests
1697-
it.skip('during search, expanding a row retriggers search', async () => {
1731+
it.knownFlake('during search, expanding a row retriggers search', async () => {
16981732
mockPerformanceSubscriptionDetailsResponse();
16991733
mockProjectDetailsResponse();
17001734

@@ -1793,10 +1827,11 @@ describe('trace view', () => {
17931827
});
17941828

17951829
// Awaits for the placeholder rendering rows to be removed
1796-
await within(container).findByText(/transaction-op-0/i);
1830+
await within(container).findAllByText(/transaction-op-0/i);
17971831

17981832
const searchInput = await screen.findByPlaceholderText('Search in trace');
1799-
await userEvent.type(searchInput, 'op-0');
1833+
await userEvent.click(searchInput);
1834+
await userEvent.paste('op-0');
18001835
await waitFor(() => expect(searchInput).toHaveValue('op-0'));
18011836

18021837
await searchToResolve();
@@ -1852,10 +1887,9 @@ describe('trace view', () => {
18521887
// row is part of the search results
18531888
await assertHighlightedRowAtIndex(container, 6);
18541889

1890+
await userEvent.clear(searchInput);
18551891
await userEvent.click(searchInput);
1856-
await userEvent.type(searchInput, '-');
1857-
await waitFor(() => expect(searchInput).toHaveValue('transaction-op-'));
1858-
await userEvent.type(searchInput, '5');
1892+
await userEvent.paste('transaction-op-5');
18591893
await waitFor(() => expect(searchInput).toHaveValue('transaction-op-5'));
18601894

18611895
await searchToResolve();
@@ -1968,37 +2002,38 @@ describe('trace view', () => {
19682002
});
19692003
});
19702004

1971-
// TODO Abdullah Khan: This is flaky, and when it flakes it takes over 90s to run
1972-
// eslint-disable-next-line jest/no-disabled-tests
1973-
it.skip('clicking a node that is already open in a tab switches to that tab and persists the previous node', async () => {
1974-
const {virtualizedContainer} = await simpleTestSetup();
1975-
const rows = getVirtualizedRows(virtualizedContainer);
1976-
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(0);
1977-
1978-
await userEvent.click(rows[5]!);
1979-
await waitFor(() => {
1980-
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(1);
1981-
});
2005+
it.knownFlake(
2006+
'clicking a node that is already open in a tab switches to that tab and persists the previous node',
2007+
async () => {
2008+
const {virtualizedContainer} = await simpleTestSetup();
2009+
const rows = getVirtualizedRows(virtualizedContainer);
2010+
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(0);
19822011

1983-
await userEvent.click(await screen.findByTestId(DRAWER_TABS_PIN_BUTTON_TEST_ID));
1984-
await userEvent.click(rows[7]!);
2012+
await userEvent.click(rows[5]!);
2013+
await waitFor(() => {
2014+
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(1);
2015+
});
19852016

1986-
await waitFor(() => {
1987-
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(2);
1988-
});
1989-
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)[1]).toHaveAttribute(
1990-
'aria-selected',
1991-
'true'
1992-
);
2017+
await userEvent.click(await screen.findByTestId(DRAWER_TABS_PIN_BUTTON_TEST_ID));
2018+
await userEvent.click(rows[7]!);
19932019

1994-
await userEvent.click(rows[5]!);
1995-
await waitFor(() => {
2020+
await waitFor(() => {
2021+
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(2);
2022+
});
19962023
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)[1]).toHaveAttribute(
19972024
'aria-selected',
19982025
'true'
19992026
);
2000-
});
2001-
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(2);
2002-
});
2027+
2028+
await userEvent.click(rows[5]!);
2029+
await waitFor(() => {
2030+
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)[1]).toHaveAttribute(
2031+
'aria-selected',
2032+
'true'
2033+
);
2034+
});
2035+
expect(screen.queryAllByTestId(DRAWER_TABS_TEST_ID)).toHaveLength(2);
2036+
}
2037+
);
20032038
});
20042039
});

0 commit comments

Comments
 (0)