Skip to content

Commit 0776db3

Browse files
authored
Send installed add-on version when available (#12530)
1 parent 7b27bc6 commit 0776db3

File tree

11 files changed

+89
-22
lines changed

11 files changed

+89
-22
lines changed

src/amo/api/abuse.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type ReportAddonParams = {|
2828
message: string,
2929
reason: string | null,
3030
location: string | null,
31+
addonVersion: string | null,
3132
|};
3233

3334
export type ReportAddonResponse = {|
@@ -38,10 +39,11 @@ export type ReportAddonResponse = {|
3839
|},
3940
message: string | null,
4041
reporter: AbuseReporter | null,
41-
reporterName: string | null,
42-
reporterEmail: string | null,
42+
reporter_name: string | null,
43+
reporter_email: string | null,
4344
reason: string | null,
4445
location: string | null,
46+
addon_version: string | null,
4547
|};
4648

4749
export function reportAddon({
@@ -52,6 +54,7 @@ export function reportAddon({
5254
message,
5355
reason,
5456
location,
57+
addonVersion,
5558
}: ReportAddonParams): Promise<ReportAddonResponse> {
5659
return callApi({
5760
auth: true,
@@ -64,6 +67,7 @@ export function reportAddon({
6467
message,
6568
reason,
6669
location,
70+
addon_version: addonVersion,
6771
},
6872
apiState: api,
6973
});

src/amo/components/FeedbackForm/index.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Helmet } from 'react-helmet';
77
import { connect } from 'react-redux';
88
import { compose } from 'redux';
99

10+
import { withInstallHelpers } from 'amo/installAddon';
1011
import { sendAddonAbuseReport } from 'amo/reducers/abuse';
1112
import { getCurrentUser } from 'amo/reducers/users';
1213
import translate from 'amo/i18n/translate';
@@ -22,6 +23,8 @@ import type { ErrorHandlerType } from 'amo/types/errorHandler';
2223
import type { I18nType } from 'amo/types/i18n';
2324
import type { AddonType } from 'amo/types/addons';
2425
import type { DispatchFunc } from 'amo/types/redux';
26+
import type { WithInstallHelpersInjectedProps } from 'amo/installAddon';
27+
import type { InstalledAddon } from 'amo/reducers/installations';
2528

2629
import './styles.scss';
2730

@@ -35,6 +38,7 @@ type PropsFromState = {|
3538
abuseReport: AddonAbuseState | null,
3639
currentUser: UserType | null,
3740
loading: boolean,
41+
installedAddon: InstalledAddon | null,
3842
|};
3943

4044
type DefaultProps = {|
@@ -45,6 +49,7 @@ type InternalProps = {|
4549
...Props,
4650
...PropsFromState,
4751
...DefaultProps,
52+
...WithInstallHelpersInjectedProps,
4853
dispatch: DispatchFunc,
4954
i18n: I18nType,
5055
|};
@@ -173,7 +178,7 @@ export class FeedbackFormBase extends React.Component<InternalProps, State> {
173178
onSubmit: HTMLElementEventHandler = (event: ElementEvent) => {
174179
event.preventDefault();
175180

176-
const { addon, dispatch, errorHandler } = this.props;
181+
const { addon, dispatch, errorHandler, installedAddon } = this.props;
177182
const { email, name, text, category, violationLocation } = this.state;
178183

179184
invariant(text.trim().length, 'A report cannot be sent with no content.');
@@ -190,6 +195,7 @@ export class FeedbackFormBase extends React.Component<InternalProps, State> {
190195
message: text,
191196
reason: category,
192197
location: violationLocation,
198+
addonVersion: installedAddon?.version || null,
193199
}),
194200
);
195201
};
@@ -457,15 +463,19 @@ export class FeedbackFormBase extends React.Component<InternalProps, State> {
457463
function mapStateToProps(state: AppState, ownProps: Props): PropsFromState {
458464
const { addon } = ownProps;
459465
const currentUser = getCurrentUser(state.users);
466+
const installedAddon =
467+
(addon?.guid && state.installations[addon.guid]) || null;
460468

461469
return {
462470
abuseReport: (addon?.slug && state.abuse.bySlug[addon.slug]) || null,
463471
currentUser,
464472
loading: state.abuse.loading,
473+
installedAddon,
465474
};
466475
}
467476

468477
const FeedbackForm: React.ComponentType<Props> = compose(
478+
withInstallHelpers,
469479
connect(mapStateToProps),
470480
translate(),
471481
)(FeedbackFormBase);

src/amo/installAddon.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ export class WithInstallHelpers extends React.Component<WithInstallHelpersIntern
220220
...payload,
221221
status,
222222
canUninstall: clientAddon.canUninstall,
223+
version: clientAddon.version,
223224
}),
224225
);
225226
},

src/amo/reducers/abuse.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,13 @@ type LoadAddonAbuseReportAction = {|
8282

8383
export function loadAddonAbuseReport({
8484
addon,
85-
reporterEmail,
86-
reporterName,
85+
reporter_email,
86+
reporter_name,
8787
message,
8888
reason,
8989
reporter,
9090
location,
91+
addon_version,
9192
}: ReportAddonResponse): LoadAddonAbuseReportAction {
9293
invariant(addon, 'addon is required');
9394
invariant(typeof message !== 'undefined', 'message must be defined');
@@ -97,12 +98,13 @@ export function loadAddonAbuseReport({
9798
type: LOAD_ADDON_ABUSE_REPORT,
9899
payload: {
99100
addon,
100-
reporterEmail,
101-
reporterName,
101+
reporter_email,
102+
reporter_name,
102103
message,
103104
reason,
104105
reporter,
105106
location,
107+
addon_version,
106108
},
107109
};
108110
}
@@ -115,6 +117,7 @@ type SendAddonAbuseReportParams = {|
115117
message: string,
116118
reason?: string | null,
117119
location?: string | null,
120+
addonVersion?: string | null,
118121
|};
119122

120123
export type SendAddonAbuseReportAction = {|
@@ -130,6 +133,7 @@ export function sendAddonAbuseReport({
130133
message,
131134
reason = null,
132135
location = null,
136+
addonVersion = null,
133137
}: SendAddonAbuseReportParams): SendAddonAbuseReportAction {
134138
invariant(addonId, 'addonId is required');
135139
invariant(errorHandlerId, 'errorHandlerId is required');
@@ -145,6 +149,7 @@ export function sendAddonAbuseReport({
145149
message,
146150
reason,
147151
location,
152+
addonVersion,
148153
},
149154
};
150155
}

src/amo/reducers/installations.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export type InstalledAddon = {
3838
needsRestart?: boolean,
3939
status: InstalledAddonStatus,
4040
url?: $PropertyType<AddonType, 'url'>,
41+
version?: string,
4142
};
4243

4344
export type InstallationsState = {
@@ -119,6 +120,7 @@ export default function installations(
119120
needsRestart: payload.needsRestart || false,
120121
status: payload.status,
121122
url: payload.url,
123+
version: payload.version,
122124
},
123125
};
124126
case START_DOWNLOAD:

src/amo/sagas/abuse.js

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export function* reportAddon({
2828
message,
2929
reason,
3030
location,
31+
addonVersion,
3132
},
3233
}: SendAddonAbuseReportAction): Saga {
3334
const errorHandler = createErrorHandler(errorHandlerId);
@@ -45,20 +46,11 @@ export function* reportAddon({
4546
message,
4647
reason: reason || null,
4748
location: location || null,
49+
addonVersion: addonVersion || null,
4850
};
4951
const response = yield call(reportAddonApi, params);
5052

51-
yield put(
52-
loadAddonAbuseReport({
53-
addon: response.addon,
54-
reporterName: response.reporter_name,
55-
reporterEmail: response.reporter_email,
56-
message: response.message,
57-
reason: response.reason,
58-
reporter: response.reporter,
59-
location: response.location,
60-
}),
61-
);
53+
yield put(loadAddonAbuseReport(response));
6254
} catch (error) {
6355
log.warn(`Reporting add-on for abuse failed: ${error}`);
6456
yield put(errorHandler.createErrorAction(error));
@@ -78,10 +70,11 @@ export function* reportAddonViaFirefox({
7870
addon: { guid: addon.guid, id: addon.id, slug: addon.slug },
7971
message: null,
8072
reporter: null,
81-
reporterEmail: null,
82-
reporterName: null,
73+
reporter_email: null,
74+
reporter_name: null,
8375
reason: null,
8476
location: null,
77+
addon_version: null,
8578
}),
8679
);
8780
}

tests/unit/amo/api/test_abuse.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ describe(__filename, () => {
3131
const reporterEmail = '[email protected]';
3232
const addonId = 'cool-addon';
3333
const location = 'both';
34+
const addonVersion = '1.2.3.4';
3435

3536
mockApi
3637
.expects('callApi')
@@ -45,6 +46,7 @@ describe(__filename, () => {
4546
reporter_email: reporterEmail,
4647
reporter_name: reporterName,
4748
location,
49+
addon_version: addonVersion,
4850
},
4951
apiState,
5052
})
@@ -64,6 +66,7 @@ describe(__filename, () => {
6466
reporterEmail,
6567
reporterName,
6668
location,
69+
addonVersion,
6770
});
6871

6972
mockApi.verify();

tests/unit/amo/pages/TestFeedback.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { extractId } from 'amo/pages/Feedback';
1010
import { loadAddonAbuseReport, sendAddonAbuseReport } from 'amo/reducers/abuse';
1111
import { loadAddon, fetchAddon } from 'amo/reducers/addons';
1212
import { clearError } from 'amo/reducers/errors';
13+
import { setInstallState } from 'amo/reducers/installations';
1314
import {
1415
createFailedErrorHandler,
1516
createFakeErrorHandler,
@@ -213,6 +214,49 @@ describe(__filename, () => {
213214
);
214215
});
215216

217+
it('sends the installed add-on version when available', async () => {
218+
const version = '2.4.5';
219+
store.dispatch(
220+
setInstallState({
221+
guid: defaultAddonGUID,
222+
version,
223+
}),
224+
);
225+
const dispatch = jest.spyOn(store, 'dispatch');
226+
render();
227+
228+
await userEvent.type(
229+
screen.getByRole('textbox', {
230+
name: 'Give details of your feedback or report',
231+
}),
232+
defaultMessage,
233+
);
234+
await userEvent.click(
235+
screen.getByRole('radio', { name: defaultReasonLabel }),
236+
);
237+
await userEvent.selectOptions(
238+
screen.getByRole('combobox', { name: 'Where is the offending content' }),
239+
defaultLocationLabel,
240+
);
241+
await userEvent.click(screen.getByRole('checkbox'));
242+
await userEvent.click(
243+
screen.getByRole('button', { name: 'Submit report' }),
244+
);
245+
246+
expect(dispatch).toHaveBeenCalledWith(
247+
sendAddonAbuseReport({
248+
errorHandlerId: getErrorHandlerId(defaultAddonGUID),
249+
addonId: defaultAddonGUID,
250+
reporterEmail: '',
251+
reporterName: '',
252+
message: defaultMessage,
253+
reason: defaultReason,
254+
location: defaultLocation,
255+
addonVersion: version,
256+
}),
257+
);
258+
});
259+
216260
it('shows success message after submission', async () => {
217261
render();
218262

tests/unit/amo/reducers/test_abuse.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ describe(__filename, () => {
103103
reporterName: 'Foxy',
104104
reporterEmail: 'made_up@email',
105105
location: 'both',
106+
addonVersion: '1.2.3',
106107
};
107108
});
108109

tests/unit/amo/reducers/test_installations.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe(__filename, () => {
2929

3030
it('adds an add-on to state', () => {
3131
const guid = '[email protected]';
32+
const version = '1.2.3.4';
3233
expect(
3334
installations(
3435
undefined,
@@ -37,6 +38,7 @@ describe(__filename, () => {
3738
guid,
3839
url: 'https://addons.cdn.mozilla.net/download/my-addon.xpi',
3940
status: UNINSTALLED,
41+
version,
4042
}),
4143
),
4244
).toEqual({
@@ -48,6 +50,7 @@ describe(__filename, () => {
4850
needsRestart: false,
4951
status: UNINSTALLED,
5052
url: 'https://addons.cdn.mozilla.net/download/my-addon.xpi',
53+
version,
5154
},
5255
});
5356
});

0 commit comments

Comments
 (0)