import {browserHistory} from 'react-router';
import {initializeOrg} from 'sentry-test/initializeOrg';
import {act, render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
import GroupStore from 'sentry/stores/groupStore';
import PageFiltersStore from 'sentry/stores/pageFiltersStore';
import ProjectsStore from 'sentry/stores/projectsStore';
import {IssueCategory} from 'sentry/types';
import {OrganizationContext} from 'sentry/views/organizationContext';
import GroupDetails from 'sentry/views/organizationGroupDetails';
import {RouteContext} from 'sentry/views/routeContext';
jest.unmock('sentry/utils/recreateRoute');
const SAMPLE_EVENT_ALERT_TEXT =
'You are viewing a sample error. Configure Sentry to start viewing real errors.';
describe('groupDetails', () => {
const group = TestStubs.Group({issueCategory: IssueCategory.ERROR});
const event = TestStubs.Event();
const project = TestStubs.Project({teams: [TestStubs.Team()]});
const selection = {environments: []};
const routes = [
{path: '/', childRoutes: [], component: null},
{childRoutes: [], component: null},
{
path: '/organizations/:orgId/issues/:groupId/',
indexRoute: null,
childRoutes: [],
componentPromise: () => {},
component: null,
},
{
componentPromise: null,
component: null,
},
];
const {organization, router, routerContext} = initializeOrg({
project,
router: {
location: {
pathname: `/organizations/org-slug/issues/${group.id}/`,
query: {},
search: '?foo=bar',
hash: '#hash',
},
params: {
groupId: group.id,
},
routes,
},
});
function MockComponent({group: groupProp, environments, eventError}) {
return (
Group Details Mock
title: {groupProp.title}
environment: {environments.join(' ')}
{eventError &&
eventError
}
);
}
const createWrapper = (props = {selection}) => {
return render(
,
{context: routerContext}
);
};
beforeEach(() => {
act(() => ProjectsStore.loadInitialData(organization.projects));
MockApiClient.addMockResponse({
url: `/issues/${group.id}/`,
body: {...group},
});
MockApiClient.addMockResponse({
url: `/issues/${group.id}/events/latest/`,
statusCode: 200,
body: {
...event,
},
});
MockApiClient.addMockResponse({
url: `/projects/org-slug/${project.slug}/issues/`,
method: 'PUT',
body: {
hasSeen: false,
},
});
MockApiClient.addMockResponse({
url: '/organizations/org-slug/projects/',
body: [project],
});
MockApiClient.addMockResponse({
url: '/organizations/org-slug/users/',
body: [],
});
MockApiClient.addMockResponse({
url: `/issues/${group.id}/first-last-release/`,
body: {firstRelease: group.firstRelease, lastRelease: group.lastRelease},
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
statusCode: 200,
body: {
data: [
{
'count()': 1,
},
],
},
});
});
afterEach(() => {
act(() => ProjectsStore.reset());
GroupStore.reset();
PageFiltersStore.reset();
MockApiClient.clearMockResponses();
});
it('renders', async function () {
act(() => ProjectsStore.reset());
createWrapper();
expect(screen.queryByText(group.title)).not.toBeInTheDocument();
act(() => ProjectsStore.loadInitialData(organization.projects));
expect(await screen.findByText(group.title, {exact: false})).toBeInTheDocument();
// Sample event alert should not show up
expect(screen.queryByText(SAMPLE_EVENT_ALERT_TEXT)).not.toBeInTheDocument();
});
it('renders error when issue is not found', async function () {
MockApiClient.addMockResponse({
url: `/issues/${group.id}/`,
statusCode: 404,
});
MockApiClient.addMockResponse({
url: `/issues/${group.id}/events/latest/`,
statusCode: 404,
});
createWrapper();
await waitFor(() =>
expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument()
);
expect(
await screen.findByText('The issue you were looking for was not found.')
).toBeInTheDocument();
});
it('renders MissingProjectMembership when trying to access issue in project the user does not belong to', async function () {
MockApiClient.addMockResponse({
url: `/issues/${group.id}/`,
statusCode: 403,
});
MockApiClient.addMockResponse({
url: `/issues/${group.id}/events/latest/`,
statusCode: 403,
});
createWrapper();
await waitFor(() =>
expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument()
);
expect(
await screen.findByText(
'No teams have access to this project yet. Ask an admin to add your team to this project.'
)
).toBeInTheDocument();
});
it('fetches issue details for a given environment', async function () {
createWrapper({
selection: {environments: ['staging']},
});
await waitFor(() =>
expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument()
);
expect(await screen.findByText('environment: staging')).toBeInTheDocument();
});
/**
* This is legacy code that I'm not even sure still happens
*/
it('redirects to new issue if params id !== id returned from API request', async function () {
MockApiClient.addMockResponse({
url: `/issues/${group.id}/`,
body: {...group, id: 'new-id'},
});
createWrapper();
expect(screen.queryByText('Group Details Mock')).not.toBeInTheDocument();
await waitFor(() => {
expect(browserHistory.push).toHaveBeenCalledTimes(1);
});
expect(browserHistory.push).toHaveBeenCalledWith(
'/organizations/org-slug/issues/new-id/?foo=bar#hash'
);
});
it('renders issue event error', async function () {
MockApiClient.addMockResponse({
url: `/issues/${group.id}/events/latest/`,
statusCode: 404,
});
createWrapper();
expect(await screen.findByText('eventError')).toBeInTheDocument();
});
it('renders for review reason', async function () {
MockApiClient.addMockResponse({
url: `/issues/${group.id}/`,
body: {
...group,
inbox: {
date_added: '2020-11-24T13:17:42.248751Z',
reason: 0,
reason_details: null,
},
},
});
act(() => ProjectsStore.reset());
createWrapper();
act(() => ProjectsStore.loadInitialData(organization.projects));
expect(await screen.findByText('New Issue')).toBeInTheDocument();
});
it('renders alert for sample event', async function () {
const sampleGroup = TestStubs.Group({issueCategory: IssueCategory.ERROR});
sampleGroup.tags.push({key: 'sample_event'});
MockApiClient.addMockResponse({
url: `/issues/${group.id}/`,
body: {...sampleGroup},
});
createWrapper();
expect(await screen.findByText(SAMPLE_EVENT_ALERT_TEXT)).toBeInTheDocument();
});
});