import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; import ProjectsStore from 'sentry/stores/projectsStore'; import {SlowestFunctionsWidget} from 'sentry/views/profiling/landing/slowestFunctionsWidget'; describe('SlowestFunctionsWidget', function () { beforeEach(function () { const project = TestStubs.Project({ id: '1', slug: 'proj-slug', }); ProjectsStore.loadInitialData([project]); }); afterEach(function () { MockApiClient.clearMockResponses(); }); it('renders errors', async function () { // return 400 for all queries MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', statusCode: 400, }); render(); // starts by rendering loading expect(screen.getByTestId('loading-indicator')).toBeInTheDocument(); // switches to errors once the api responds with an error expect(await screen.findByTestId('error-indicator')).toBeInTheDocument(); }); it('renders example transactions', async function () { // for the slowest functions query MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', body: { data: [ { 'project.id': 1, package: 'foo', function: 'bar', 'sum()': 150, }, { 'project.id': 1, package: 'baz', function: 'qux', 'sum()': 100, }, ], }, match: [ MockApiClient.matchQuery({ dataset: 'profileFunctions', query: 'is_application:1', field: ['project.id', 'package', 'function', 'count()', 'sum()'], }), ], }); // for the totals query MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', body: {data: [{'project.id': 1, 'sum()': 2500000}]}, match: [ MockApiClient.matchQuery({ dataset: 'profileFunctions', query: 'is_application:1', field: ['project.id', 'sum()'], project: [1], }), ], }); // first function examples MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', body: { data: [ { transaction: 'transaction-1', 'count()': 1000, 'sum()': 1000000, 'examples()': [ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', ], }, { transaction: 'transaction-2', 'count()': 2500, 'sum()': 500000, 'examples()': ['cccccccccccccccccccccccccccccccc'], }, ], }, match: [ MockApiClient.matchQuery({ dataset: 'profileFunctions', query: 'is_application:1 project.id:1 package:foo function:bar', field: ['transaction', 'count()', 'sum()', 'examples()'], }), ], }); // second function examples MockApiClient.addMockResponse({ url: '/organizations/org-slug/events/', body: { data: [ { transaction: 'transaction-3', 'count()': 2000, 'sum()': 2000000, 'examples()': [ 'dddddddddddddddddddddddddddddddd', 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', ], }, { transaction: 'transaction-4', 'count()': 3500, 'sum()': 700000, 'examples()': ['ffffffffffffffffffffffffffffffff'], }, ], }, match: [ MockApiClient.matchQuery({ dataset: 'profileFunctions', query: 'is_application:1 project.id:1 package:baz function:qux', field: ['transaction', 'count()', 'sum()', 'examples()'], }), ], }); render(); // starts by rendering loading expect(screen.getByTestId('loading-indicator')).toBeInTheDocument(); // switches to the transactions list once the api responds with data expect(await screen.findByTestId('transactions-list')).toBeInTheDocument(); // headers expect(screen.getByText('Transaction')).toBeInTheDocument(); expect(screen.getByText('Count')).toBeInTheDocument(); expect(screen.getByText('Total Self Time')).toBeInTheDocument(); // first row const transaction1 = screen.getByText('transaction-1'); expect(transaction1).toBeInTheDocument(); expect(transaction1).toHaveAttribute( 'href', '/organizations/org-slug/profiling/profile/proj-slug/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/flamechart/?frameName=bar&framePackage=foo' ); expect(screen.getByText('1k')).toBeInTheDocument(); expect(screen.getByText('1.00ms')).toBeInTheDocument(); // second row const transaction2 = screen.getByText('transaction-2'); expect(transaction2).toBeInTheDocument(); expect(transaction2).toHaveAttribute( 'href', '/organizations/org-slug/profiling/profile/proj-slug/cccccccccccccccccccccccccccccccc/flamechart/?frameName=bar&framePackage=foo' ); expect(screen.getByText('2.5k')).toBeInTheDocument(); expect(screen.getByText('0.50ms')).toBeInTheDocument(); // toggle the second function const toggles = screen.getAllByRole('button', {}); expect(toggles.length).toEqual(2); await userEvent.click(toggles[1]); // first row const transaction3 = screen.getByText('transaction-3'); expect(transaction3).toBeInTheDocument(); expect(transaction3).toHaveAttribute( 'href', '/organizations/org-slug/profiling/profile/proj-slug/dddddddddddddddddddddddddddddddd/flamechart/?frameName=qux&framePackage=baz' ); expect(screen.getByText('2k')).toBeInTheDocument(); expect(screen.getByText('2.00ms')).toBeInTheDocument(); // second row const transaction4 = screen.getByText('transaction-4'); expect(transaction4).toBeInTheDocument(); expect(transaction4).toHaveAttribute( 'href', '/organizations/org-slug/profiling/profile/proj-slug/ffffffffffffffffffffffffffffffff/flamechart/?frameName=qux&framePackage=baz' ); expect(screen.getByText('3.5k')).toBeInTheDocument(); expect(screen.getByText('0.70ms')).toBeInTheDocument(); }); });