Skip to content

Commit 0485d11

Browse files
authored
feat(feedback): Add source to feedback payload (#9494)
`sendFeedback` now sends a `source` property in the feedback context. `source` will be `api` if you call `sendFeedback` directly, otherwise `widget` when called from widget UI.
1 parent 432495d commit 0485d11

File tree

7 files changed

+110
-3
lines changed

7 files changed

+110
-3
lines changed

packages/feedback/src/sendFeedback.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ interface SendFeedbackParams {
1010
name?: string;
1111
email?: string;
1212
url?: string;
13+
source?: string;
1314
}
1415

1516
/**
1617
* Public API to send a Feedback item to Sentry
1718
*/
1819
export function sendFeedback(
19-
{ name, email, message, url = getLocationHref() }: SendFeedbackParams,
20+
{ name, email, message, source = 'api', url = getLocationHref() }: SendFeedbackParams,
2021
{ includeReplay = true }: SendFeedbackOptions = {},
2122
): ReturnType<typeof sendFeedbackRequest> {
2223
const client = getCurrentHub().getClient<BrowserClient>();
@@ -37,6 +38,7 @@ export function sendFeedback(
3738
message,
3839
url,
3940
replay_id: replayId,
41+
source,
4042
},
4143
});
4244
}

packages/feedback/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface SendFeedbackData {
1212
email?: string;
1313
replay_id?: string;
1414
name?: string;
15+
source?: string;
1516
};
1617
}
1718

packages/feedback/src/util/handleFeedbackSubmit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export async function handleFeedbackSubmit(
2929
dialog.hideError();
3030

3131
try {
32-
const resp = await sendFeedback(feedback, options);
32+
const resp = await sendFeedback({ ...feedback, source: 'widget' }, options);
3333

3434
// Success!
3535
return resp;

packages/feedback/src/util/sendFeedbackRequest.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { prepareFeedbackEvent } from './prepareFeedbackEvent';
88
* Send feedback using transport
99
*/
1010
export async function sendFeedbackRequest({
11-
feedback: { message, email, name, replay_id, url },
11+
feedback: { message, email, name, source, replay_id, url },
1212
}: SendFeedbackData): Promise<void | TransportMakeRequestResponse> {
1313
const hub = getCurrentHub();
1414
const client = hub.getClient();
@@ -28,6 +28,7 @@ export async function sendFeedbackRequest({
2828
message,
2929
replay_id,
3030
url,
31+
source,
3132
},
3233
},
3334
type: 'feedback',
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { getCurrentHub } from '@sentry/core';
2+
3+
import { sendFeedback } from '../src/sendFeedback';
4+
import { mockSdk } from './utils/mockSdk';
5+
6+
describe('sendFeedback', () => {
7+
it('sends feedback', async () => {
8+
mockSdk();
9+
const mockTransport = jest.spyOn(getCurrentHub().getClient()!.getTransport()!, 'send');
10+
11+
await sendFeedback({
12+
name: 'doe',
13+
14+
message: 'mi',
15+
});
16+
expect(mockTransport).toHaveBeenCalledWith([
17+
{ event_id: expect.any(String), sent_at: expect.any(String) },
18+
[
19+
[
20+
{ type: 'feedback' },
21+
{
22+
breadcrumbs: undefined,
23+
contexts: {
24+
feedback: {
25+
contact_email: '[email protected]',
26+
message: 'mi',
27+
name: 'doe',
28+
replay_id: undefined,
29+
source: 'api',
30+
url: 'http://localhost/',
31+
},
32+
},
33+
environment: 'production',
34+
event_id: expect.any(String),
35+
platform: 'javascript',
36+
timestamp: expect.any(Number),
37+
type: 'feedback',
38+
},
39+
],
40+
],
41+
]);
42+
});
43+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { Envelope, Transport, TransportMakeRequestResponse } from '@sentry/types';
2+
3+
import type { TestClientOptions } from '../utils/TestClient';
4+
import { getDefaultClientOptions, init } from '../utils/TestClient';
5+
6+
export interface MockSdkParams {
7+
sentryOptions?: Partial<TestClientOptions>;
8+
}
9+
10+
class MockTransport implements Transport {
11+
send: (request: Envelope) => PromiseLike<TransportMakeRequestResponse>;
12+
13+
constructor() {
14+
const send: ((request: Envelope) => PromiseLike<TransportMakeRequestResponse>) & {
15+
__sentry__baseTransport__?: boolean;
16+
} = jest.fn(async () => {
17+
return {
18+
statusCode: 200,
19+
};
20+
});
21+
22+
send.__sentry__baseTransport__ = true;
23+
this.send = send;
24+
}
25+
26+
async flush() {
27+
return true;
28+
}
29+
async sendEvent(_e: Event) {
30+
return {
31+
status: 'skipped',
32+
event: 'ok',
33+
type: 'transaction',
34+
};
35+
}
36+
async sendSession() {
37+
return;
38+
}
39+
async recordLostEvent() {
40+
return;
41+
}
42+
async close() {
43+
return;
44+
}
45+
}
46+
47+
export async function mockSdk({ sentryOptions }: MockSdkParams = {}): Promise<void> {
48+
init({
49+
...getDefaultClientOptions(),
50+
dsn: 'https://[email protected]/1',
51+
autoSessionTracking: false,
52+
sendClientReports: false,
53+
transport: () => new MockTransport(),
54+
replaysSessionSampleRate: 0.0,
55+
replaysOnErrorSampleRate: 0.0,
56+
...sentryOptions,
57+
});
58+
}

packages/feedback/test/widget/createWidget.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ describe('createWidget', () => {
155155
message: 'My feedback',
156156
url: 'http://localhost/',
157157
replay_id: undefined,
158+
source: 'widget',
158159
},
159160
});
160161

@@ -194,6 +195,7 @@ describe('createWidget', () => {
194195
message: 'My feedback',
195196
url: 'http://localhost/',
196197
replay_id: undefined,
198+
source: 'widget',
197199
},
198200
});
199201

0 commit comments

Comments
 (0)