Skip to content

Commit e824348

Browse files
authored
feat(issues): Update group on resolve/archive (#92170)
1 parent 2d968f3 commit e824348

File tree

2 files changed

+78
-27
lines changed

2 files changed

+78
-27
lines changed

static/app/views/issueDetails/actions/index.spec.tsx

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {EventStacktraceExceptionFixture} from 'sentry-fixture/eventStacktraceExc
33
import {GroupFixture} from 'sentry-fixture/group';
44
import {OrganizationFixture} from 'sentry-fixture/organization';
55
import {ProjectFixture} from 'sentry-fixture/project';
6-
import {RouterFixture} from 'sentry-fixture/routerFixture';
76

87
import {
98
render,
@@ -20,6 +19,7 @@ import ModalStore from 'sentry/stores/modalStore';
2019
import {GroupStatus, IssueCategory} from 'sentry/types/group';
2120
import * as analytics from 'sentry/utils/analytics';
2221
import {GroupActions} from 'sentry/views/issueDetails/actions';
22+
import {useGroup} from 'sentry/views/issueDetails/useGroup';
2323

2424
const project = ProjectFixture({
2525
id: '2448',
@@ -68,7 +68,6 @@ describe('GroupActions', function () {
6868
<GroupActions group={group} project={project} disabled={false} event={null} />,
6969
{
7070
organization,
71-
deprecatedRouterMocks: true,
7271
}
7372
);
7473
expect(await screen.findByRole('button', {name: 'Resolve'})).toBeInTheDocument();
@@ -90,7 +89,6 @@ describe('GroupActions', function () {
9089
<GroupActions group={group} project={project} disabled={false} event={null} />,
9190
{
9291
organization,
93-
deprecatedRouterMocks: true,
9492
}
9593
);
9694
await userEvent.click(screen.getByRole('button', {name: 'Subscribe'}));
@@ -120,7 +118,6 @@ describe('GroupActions', function () {
120118
<GroupActions group={group} project={project} disabled={false} event={null} />,
121119
{
122120
organization,
123-
deprecatedRouterMocks: true,
124121
}
125122
);
126123

@@ -148,7 +145,6 @@ describe('GroupActions', function () {
148145
<GroupActions group={group} project={project} event={event} disabled={false} />,
149146
{
150147
organization,
151-
deprecatedRouterMocks: true,
152148
}
153149
);
154150

@@ -167,7 +163,6 @@ describe('GroupActions', function () {
167163
<GroupActions group={group} project={project} event={event} disabled={false} />,
168164
{
169165
organization,
170-
deprecatedRouterMocks: true,
171166
}
172167
);
173168

@@ -184,7 +179,6 @@ describe('GroupActions', function () {
184179

185180
describe('delete', function () {
186181
it('opens delete confirm modal from more actions dropdown', async () => {
187-
const router = RouterFixture();
188182
const org = OrganizationFixture({
189183
...organization,
190184
access: [...organization.access, 'event:admin'],
@@ -199,15 +193,13 @@ describe('GroupActions', function () {
199193
method: 'DELETE',
200194
body: {},
201195
});
202-
render(
196+
const {router} = render(
203197
<Fragment>
204198
<GlobalModal />
205199
<GroupActions group={group} project={project} disabled={false} event={null} />
206200
</Fragment>,
207201
{
208-
router,
209202
organization: org,
210-
deprecatedRouterMocks: true,
211203
}
212204
);
213205

@@ -222,14 +214,15 @@ describe('GroupActions', function () {
222214
await userEvent.click(within(modal).getByRole('button', {name: 'Delete'}));
223215

224216
expect(deleteMock).toHaveBeenCalled();
225-
expect(router.push).toHaveBeenCalledWith({
226-
pathname: `/organizations/${org.slug}/issues/`,
227-
query: {project: project.id},
228-
});
217+
expect(router.location).toEqual(
218+
expect.objectContaining({
219+
pathname: `/organizations/${org.slug}/issues/`,
220+
query: {project: project.id},
221+
})
222+
);
229223
});
230224

231225
it('delete for issue platform', async () => {
232-
const router = RouterFixture();
233226
const org = OrganizationFixture({
234227
...organization,
235228
access: [...organization.access, 'event:admin'],
@@ -244,7 +237,7 @@ describe('GroupActions', function () {
244237
method: 'DELETE',
245238
body: {},
246239
});
247-
render(
240+
const {router} = render(
248241
<Fragment>
249242
<GlobalModal />
250243
<GroupActions
@@ -255,9 +248,7 @@ describe('GroupActions', function () {
255248
/>
256249
</Fragment>,
257250
{
258-
router,
259251
organization: org,
260-
deprecatedRouterMocks: true,
261252
}
262253
);
263254

@@ -272,10 +263,12 @@ describe('GroupActions', function () {
272263
await userEvent.click(within(modal).getByRole('button', {name: 'Delete'}));
273264

274265
expect(deleteMock).toHaveBeenCalled();
275-
expect(router.push).toHaveBeenCalledWith({
276-
pathname: `/organizations/${org.slug}/issues/`,
277-
query: {project: project.id},
278-
});
266+
expect(router.location).toEqual(
267+
expect.objectContaining({
268+
pathname: `/organizations/${org.slug}/issues/`,
269+
query: {project: project.id},
270+
})
271+
);
279272
});
280273
});
281274

@@ -288,10 +281,7 @@ describe('GroupActions', function () {
288281

289282
const {rerender} = render(
290283
<GroupActions group={group} project={project} disabled={false} event={null} />,
291-
{
292-
organization,
293-
deprecatedRouterMocks: true,
294-
}
284+
{organization}
295285
);
296286

297287
await userEvent.click(screen.getByRole('button', {name: 'Resolve'}));
@@ -363,4 +353,51 @@ describe('GroupActions', function () {
363353
})
364354
);
365355
});
356+
357+
it('refetches group data after resolve action using useGroup hook', async () => {
358+
const issuesApi = MockApiClient.addMockResponse({
359+
url: `/projects/${organization.slug}/project/issues/`,
360+
method: 'PUT',
361+
body: {...group, status: 'resolved'},
362+
});
363+
364+
// Mock the group fetch API that useGroup hook will call
365+
const groupFetchApi = MockApiClient.addMockResponse({
366+
url: `/organizations/${organization.slug}/issues/${group.id}/`,
367+
method: 'GET',
368+
body: group,
369+
});
370+
371+
function GroupActionsWrapper() {
372+
const {data: groupData, isLoading} = useGroup({groupId: group.id});
373+
374+
if (isLoading || !groupData) {
375+
return <div>Loading...</div>;
376+
}
377+
378+
return (
379+
<GroupActions group={groupData} project={project} disabled={false} event={null} />
380+
);
381+
}
382+
383+
render(<GroupActionsWrapper />, {organization});
384+
385+
await waitFor(() => {
386+
expect(groupFetchApi).toHaveBeenCalledTimes(1);
387+
});
388+
389+
await userEvent.click(screen.getByRole('button', {name: 'Resolve'}));
390+
391+
expect(issuesApi).toHaveBeenCalledWith(
392+
`/projects/${organization.slug}/project/issues/`,
393+
expect.objectContaining({
394+
data: {status: 'resolved', statusDetails: {}, substatus: null},
395+
})
396+
);
397+
398+
// Verify that the group is fetched a second time after the action to refresh data
399+
await waitFor(() => {
400+
expect(groupFetchApi).toHaveBeenCalledTimes(2);
401+
});
402+
});
366403
});

static/app/views/issueDetails/actions/index.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {getAnalyticsDataForGroup} from 'sentry/utils/events';
4747
import {uniqueId} from 'sentry/utils/guid';
4848
import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig';
4949
import {getAnalyicsDataForProject} from 'sentry/utils/projects';
50+
import {useQueryClient} from 'sentry/utils/queryClient';
5051
import useApi from 'sentry/utils/useApi';
5152
import {useLocation} from 'sentry/utils/useLocation';
5253
import {useNavigate} from 'sentry/utils/useNavigate';
@@ -56,7 +57,11 @@ import {NewIssueExperienceButton} from 'sentry/views/issueDetails/actions/newIss
5657
import ShareIssueModal from 'sentry/views/issueDetails/actions/shareModal';
5758
import SubscribeAction from 'sentry/views/issueDetails/actions/subscribeAction';
5859
import {Divider} from 'sentry/views/issueDetails/divider';
59-
import {useHasStreamlinedUI} from 'sentry/views/issueDetails/utils';
60+
import {makeFetchGroupQueryKey} from 'sentry/views/issueDetails/useGroup';
61+
import {
62+
useEnvironmentsFromUrl,
63+
useHasStreamlinedUI,
64+
} from 'sentry/views/issueDetails/utils';
6065

6166
type UpdateData =
6267
| {isBookmarked: boolean}
@@ -81,6 +86,8 @@ export function GroupActions({group, project, disabled, event}: GroupActionsProp
8186
const navigate = useNavigate();
8287
const location = useLocation();
8388
const hasStreamlinedUI = useHasStreamlinedUI();
89+
const queryClient = useQueryClient();
90+
const environments = useEnvironmentsFromUrl();
8491

8592
const bookmarkKey = group.isBookmarked ? 'unbookmark' : 'bookmark';
8693
const bookmarkTitle = group.isBookmarked ? t('Remove bookmark') : t('Bookmark');
@@ -200,6 +207,13 @@ export function GroupActions({group, project, disabled, event}: GroupActionsProp
200207
complete: () => {
201208
clearIndicators();
202209
onComplete?.();
210+
queryClient.invalidateQueries({
211+
queryKey: makeFetchGroupQueryKey({
212+
organizationSlug: organization.slug,
213+
groupId: group.id,
214+
environments,
215+
}),
216+
});
203217
},
204218
}
205219
);

0 commit comments

Comments
 (0)