import {EventFixture} from 'sentry-fixture/event';
import {GroupFixture} from 'sentry-fixture/group';
import {TagsFixture} from 'sentry-fixture/tags';
import {TeamFixture} from 'sentry-fixture/team';
import {UserFixture} from 'sentry-fixture/user';
import {initializeOrg} from 'sentry-test/initializeOrg';
import {
render,
screen,
userEvent,
waitFor,
within,
} from 'sentry-test/reactTestingLibrary';
import MemberListStore from 'sentry/stores/memberListStore';
import type {TeamParticipant, UserParticipant} from 'sentry/types/group';
import GroupSidebar from './groupSidebar';
describe('GroupSidebar', function () {
let group = GroupFixture();
const {organization, project} = initializeOrg();
const environment = 'production';
let tagsMock: jest.Mock;
beforeEach(function () {
MemberListStore.loadInitialData([]);
MockApiClient.addMockResponse({
url: '/projects/org-slug/project-slug/events/1/committers/',
body: {committers: []},
});
MockApiClient.addMockResponse({
url: '/projects/org-slug/project-slug/events/1/owners/',
body: {
owners: [],
rules: [],
},
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/issues/1/integrations/`,
body: [],
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/issues/1/`,
body: group,
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/issues/1/current-release/`,
body: {},
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/issues/1/external-issues/`,
body: [],
});
MockApiClient.addMockResponse({
url: `/projects/${organization.slug}/${project.slug}/codeowners/`,
body: [],
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/prompts-activity/`,
body: {},
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/code-mappings/?project=-1`,
method: 'GET',
body: [],
});
tagsMock = MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/issues/1/tags/`,
body: TagsFixture(),
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/users/`,
body: [],
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/issues/${group.id}/first-last-release/`,
method: 'GET',
});
});
afterEach(function () {
MockApiClient.clearMockResponses();
});
describe('sidebar', () => {
it('should make a request to the /tags/ endpoint to get top values', async () => {
render(
);
expect(await screen.findByText('browser')).toBeInTheDocument();
expect(tagsMock).toHaveBeenCalled();
});
});
describe('renders with tags', function () {
it('renders', async function () {
render(
);
expect(await screen.findByText('browser')).toBeInTheDocument();
expect(screen.getByText('device')).toBeInTheDocument();
expect(screen.getByText('url')).toBeInTheDocument();
expect(screen.getByText('environment')).toBeInTheDocument();
expect(screen.getByText('user')).toBeInTheDocument();
});
});
describe('environment toggle', function () {
it('re-requests tags with correct environment', async function () {
const stagingEnv = 'staging';
const {rerender} = render(
);
expect(await screen.findByText('browser')).toBeInTheDocument();
expect(tagsMock).toHaveBeenCalledTimes(1);
rerender(
);
expect(await screen.findByText('browser')).toBeInTheDocument();
expect(tagsMock).toHaveBeenCalledTimes(2);
expect(tagsMock).toHaveBeenCalledWith(
'/organizations/org-slug/issues/1/tags/',
expect.objectContaining({
query: expect.objectContaining({
environment: ['staging'],
}),
})
);
});
});
describe('renders without tags', function () {
beforeEach(function () {
group = GroupFixture();
MockApiClient.addMockResponse({
url: '/organization/org-slug/issues/1/',
body: group,
});
MockApiClient.addMockResponse({
url: '/organizations/org-slug/issues/1/tags/',
body: [],
});
});
it('renders empty text', async function () {
render(
);
expect(
await screen.findByText('No tags found in the selected environments')
).toBeInTheDocument();
});
});
it('expands participants and viewers', async () => {
const org = {
...organization,
};
const teams: TeamParticipant[] = [{...TeamFixture(), type: 'team'}];
const users: UserParticipant[] = [
{
...UserFixture({
id: '2',
name: 'John Smith',
email: 'johnsmith@example.com',
}),
type: 'user',
},
{
...UserFixture({
id: '3',
name: 'Sohn Jmith',
email: 'sohnjmith@example.com',
}),
type: 'user',
},
];
render(
,
{
organization: org,
}
);
expect(
await screen.findByRole('heading', {name: 'Participants (1 Team, 2 Individuals)'})
).toBeInTheDocument();
expect(screen.queryByText('#team-slug')).not.toBeInTheDocument();
await userEvent.click(
screen.getAllByRole('button', {name: 'Expand Participants'})[0]
);
await waitFor(() => expect(screen.getByText('#team-slug')).toBeVisible());
});
describe('displays mobile tags when issue platform is mobile', function () {
beforeEach(function () {
group = GroupFixture();
MockApiClient.addMockResponse({
url: '/issues/1/',
body: group,
});
});
it('renders mobile tags on top of tag summary for mobile platforms', async function () {
render(
);
await waitFor(() => expect(tagsMock).toHaveBeenCalled());
expect(
within(await screen.findByTestId('top-distribution-wrapper')).getByText('device')
).toBeInTheDocument();
});
it('does not render mobile tags on top of tag summary for non mobile platforms', async function () {
render(
);
await waitFor(() => expect(tagsMock).toHaveBeenCalled());
expect(
within(await screen.findByTestId('top-distribution-wrapper')).queryByText(
'device'
)
).not.toBeInTheDocument();
});
});
});