Skip to content

Commit 9b7d41e

Browse files
committed
CrateSidebar: Link report button to support page
The report form's crate field should be automatically filled when navigating from the report button in the CrateSidebar.
1 parent 10106d8 commit 9b7d41e

File tree

3 files changed

+254
-3
lines changed

3 files changed

+254
-3
lines changed

app/components/crate-sidebar.hbs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,13 @@
130130
{{/unless}}
131131
{{/if}}
132132

133-
<a
134-
href="mailto:[email protected]?subject=The%20%22{{@crate.name}}%22%20crate&body=I'm%20reporting%20the%20https%3A%2F%2Fcrates.io%2Fcrates%2F{{@crate.name}}%20crate%20because%3A%0A%0A-%20%5B%20%5D%20it%20contains%20spam%0A-%20%5B%20%5D%20it%20is%20name-squatting%20(reserving%20a%20crate%20name%20without%20content)%0A-%20%5B%20%5D%20it%20is%20abusive%20or%20otherwise%20harmful%0A-%20%5B%20%5D%20it%20contains%20a%20vulnerability%20(please%20try%20to%20contact%20the%20crate%20author%20first)%0A-%20%5B%20%5D%20it%20is%20violating%20the%20usage%20policy%20in%20some%20other%20way%20(please%20specify%20below)%0A%0AAdditional%20details%3A%0A%0A%3Cplease%20add%20more%20information%20if%20you%20can%3E"
133+
<LinkTo
134+
@route="support"
135+
@query={{hash inquire="crate-violation" crate=@crate.name}}
136+
data-test-id="link-crate-report"
135137
local-class="report-button"
136138
>
137139
Report crate
138-
</a>
140+
</LinkTo>
139141
</div>
140142
</section>

e2e/acceptance/support.spec.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,138 @@ Additional details:
178178
179179
Additional details:
180180
181+
test detail
182+
`;
183+
let subject = `The "nanomsg" crate`;
184+
let address = '[email protected]';
185+
let mailto = `mailto:${address}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
186+
// wait for `window.open()` to be called
187+
await page.waitForFunction(() => !!globalThis.openKwargs);
188+
await page.waitForFunction(expect => globalThis.openKwargs.url === expect, mailto);
189+
await page.waitForFunction(expect => globalThis.openKwargs.target === expect, '_self');
190+
});
191+
});
192+
193+
test.describe('reporting a crate from crate page', () => {
194+
test.beforeEach(async ({ page, mirage }) => {
195+
await mirage.config({ trackRequests: true });
196+
await mirage.addHook(server => {
197+
globalThis._routes = server._config.routes;
198+
let crate = server.create('crate', { name: 'nanomsg' });
199+
server.create('version', { crate, num: '0.6.0' });
200+
});
201+
// mock `window.open()`
202+
await page.addInitScript(() => {
203+
globalThis.open = (url, target, features) => {
204+
globalThis.openKwargs = { url, target, features };
205+
return { document: { write() {}, close() {} }, close() {} } as ReturnType<(typeof globalThis)['open']>;
206+
};
207+
});
208+
209+
await page.goto('/crates/nanomsg');
210+
await page.getByTestId('link-crate-report').click();
211+
await expect(page).toHaveURL('/support?crate=nanomsg&inquire=crate-violation');
212+
await expect(page.getByTestId('crate-input')).toHaveValue('nanomsg');
213+
});
214+
215+
test('empty crate should shows errors', async ({ page }) => {
216+
const crateInput = page.getByTestId('crate-input');
217+
await crateInput.fill('');
218+
await expect(crateInput).toHaveValue('');
219+
const reportButton = page.getByTestId('report-button');
220+
await reportButton.click();
221+
222+
await expect(page.getByTestId('crate-invalid')).toBeVisible();
223+
await expect(page.getByTestId('reasons-invalid')).toBeVisible();
224+
await expect(page.getByTestId('detail-invalid')).not.toBeVisible();
225+
226+
await page.waitForFunction(() => globalThis.openKwargs === undefined);
227+
});
228+
229+
test('other reason selected without given detail shows an error', async ({ page }) => {
230+
const spam = page.getByTestId('spam-checkbox');
231+
await spam.check();
232+
await expect(spam).toBeChecked();
233+
const other = page.getByTestId('other-checkbox');
234+
await other.check();
235+
await expect(other).toBeChecked();
236+
const detailInput = page.getByTestId('detail-input');
237+
await expect(detailInput).toHaveValue('');
238+
const reportButton = page.getByTestId('report-button');
239+
await reportButton.click();
240+
241+
await expect(page.getByTestId('crate-invalid')).not.toBeVisible();
242+
await expect(page.getByTestId('reasons-invalid')).not.toBeVisible();
243+
await expect(page.getByTestId('detail-invalid')).toBeVisible();
244+
245+
await page.waitForFunction(() => globalThis.openKwargs === undefined);
246+
});
247+
248+
test('valid form without detail', async ({ page }) => {
249+
const spam = page.getByTestId('spam-checkbox');
250+
await spam.check();
251+
await expect(spam).toBeChecked();
252+
const detailInput = page.getByTestId('detail-input');
253+
await expect(detailInput).toHaveValue('');
254+
255+
await page.waitForFunction(() => globalThis.openKwargs === undefined);
256+
const reportButton = page.getByTestId('report-button');
257+
await reportButton.click();
258+
259+
await expect(page.getByTestId('crate-invalid')).not.toBeVisible();
260+
await expect(page.getByTestId('reasons-invalid')).not.toBeVisible();
261+
await expect(page.getByTestId('detail-invalid')).not.toBeVisible();
262+
263+
let body = `I'm reporting the https://crates.io/crates/nanomsg crate because:
264+
265+
- [x] it contains spam
266+
- [ ] it is name-squatting (reserving a crate name without content)
267+
- [ ] it is abusive or otherwise harmful
268+
- [ ] it contains a vulnerability (please try to contact the crate author first)
269+
- [ ] it is violating the usage policy in some other way (please specify below)
270+
271+
Additional details:
272+
273+
274+
`;
275+
let subject = `The "nanomsg" crate`;
276+
let address = '[email protected]';
277+
let mailto = `mailto:${address}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
278+
// wait for `window.open()` to be called
279+
await page.waitForFunction(() => !!globalThis.openKwargs);
280+
await page.waitForFunction(expect => globalThis.openKwargs.url === expect, mailto);
281+
await page.waitForFunction(expect => globalThis.openKwargs.target === expect, '_self');
282+
});
283+
284+
test('valid form with required detail', async ({ page }) => {
285+
const spam = page.getByTestId('spam-checkbox');
286+
await spam.check();
287+
await expect(spam).toBeChecked();
288+
const other = page.getByTestId('other-checkbox');
289+
await other.check();
290+
await expect(other).toBeChecked();
291+
const detailInput = page.getByTestId('detail-input');
292+
await detailInput.fill('test detail');
293+
await expect(detailInput).toHaveValue('test detail');
294+
295+
await page.waitForFunction(() => globalThis.openKwargs === undefined);
296+
const reportButton = page.getByTestId('report-button');
297+
await reportButton.click();
298+
299+
await expect(page.getByTestId('crate-invalid')).not.toBeVisible();
300+
await expect(page.getByTestId('reasons-invalid')).not.toBeVisible();
301+
await expect(page.getByTestId('detail-invalid')).not.toBeVisible();
302+
303+
let body = `I'm reporting the https://crates.io/crates/nanomsg crate because:
304+
305+
- [x] it contains spam
306+
- [ ] it is name-squatting (reserving a crate name without content)
307+
- [ ] it is abusive or otherwise harmful
308+
- [ ] it contains a vulnerability (please try to contact the crate author first)
309+
- [x] it is violating the usage policy in some other way (please specify below)
310+
311+
Additional details:
312+
181313
test detail
182314
`;
183315
let subject = `The "nanomsg" crate`;

tests/acceptance/support-test.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,123 @@ Additional details:
180180
181181
Additional details:
182182
183+
test detail
184+
`;
185+
let subject = `The "nanomsg" crate`;
186+
let address = '[email protected]';
187+
let mailto = `mailto:${address}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
188+
assert.true(!!window.openKwargs);
189+
assert.strictEqual(window.openKwargs.url, mailto);
190+
assert.strictEqual(window.openKwargs.target, '_self');
191+
});
192+
});
193+
194+
module('reporting a crate from crate page', function () {
195+
setupWindowMock(hooks);
196+
197+
async function prepare(context, assert) {
198+
let server = context.server;
199+
let crate = server.create('crate', { name: 'nanomsg' });
200+
server.create('version', { crate, num: '0.6.0' });
201+
202+
window.open = (url, target, features) => {
203+
window.openKwargs = { url, target, features };
204+
return { document: { write() {}, close() {} }, close() {} };
205+
};
206+
207+
await visit('/crates/nanomsg');
208+
await click('[data-test-id="link-crate-report"]');
209+
assert.strictEqual(currentURL(), '/support?crate=nanomsg&inquire=crate-violation');
210+
assert.dom('[data-test-id="crate-input"]').hasValue('nanomsg');
211+
}
212+
213+
test('empty crate should shows errors', async function (assert) {
214+
await prepare(this, assert);
215+
await fillIn('[data-test-id="crate-input"]', '');
216+
assert.dom('[data-test-id="crate-input"]').hasValue('');
217+
await click('[data-test-id="report-button"]');
218+
219+
assert.dom('[data-test-id="crate-invalid"]').exists();
220+
assert.dom('[data-test-id="reasons-invalid"]').exists();
221+
assert.dom('[data-test-id="detail-invalid"]').doesNotExist();
222+
223+
assert.strictEqual(window.openKwargs, undefined);
224+
});
225+
226+
test('other reason selected without given detail shows an error', async function (assert) {
227+
await prepare(this, assert);
228+
229+
await click('[data-test-id="spam-checkbox"]');
230+
assert.dom('[data-test-id="spam-checkbox"]').isChecked();
231+
await click('[data-test-id="other-checkbox"]');
232+
assert.dom('[data-test-id="other-checkbox"]').isChecked();
233+
assert.dom('[data-test-id="detail-input"]').hasValue('');
234+
await click('[data-test-id="report-button"]');
235+
236+
assert.dom('[data-test-id="crate-invalid"]').doesNotExist();
237+
assert.dom('[data-test-id="reasons-invalid"]').doesNotExist();
238+
assert.dom('[data-test-id="detail-invalid"]').exists();
239+
240+
assert.strictEqual(window.openKwargs, undefined);
241+
});
242+
243+
test('valid form without detail', async function (assert) {
244+
await prepare(this, assert);
245+
246+
await click('[data-test-id="spam-checkbox"]');
247+
assert.dom('[data-test-id="spam-checkbox"]').isChecked();
248+
assert.dom('[data-test-id="detail-input"]').hasValue('');
249+
await click('[data-test-id="report-button"]');
250+
251+
assert.dom('[data-test-id="crate-invalid"]').doesNotExist();
252+
assert.dom('[data-test-id="reasons-invalid"]').doesNotExist();
253+
assert.dom('[data-test-id="detail-invalid"]').doesNotExist();
254+
255+
let body = `I'm reporting the https://crates.io/crates/nanomsg crate because:
256+
257+
- [x] it contains spam
258+
- [ ] it is name-squatting (reserving a crate name without content)
259+
- [ ] it is abusive or otherwise harmful
260+
- [ ] it contains a vulnerability (please try to contact the crate author first)
261+
- [ ] it is violating the usage policy in some other way (please specify below)
262+
263+
Additional details:
264+
265+
266+
`;
267+
let subject = `The "nanomsg" crate`;
268+
let address = '[email protected]';
269+
let mailto = `mailto:${address}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
270+
assert.true(!!window.openKwargs);
271+
assert.strictEqual(window.openKwargs.url, mailto);
272+
assert.strictEqual(window.openKwargs.target, '_self');
273+
});
274+
275+
test('valid form with required detail', async function (assert) {
276+
await prepare(this, assert);
277+
278+
await click('[data-test-id="spam-checkbox"]');
279+
assert.dom('[data-test-id="spam-checkbox"]').isChecked();
280+
await click('[data-test-id="other-checkbox"]');
281+
assert.dom('[data-test-id="other-checkbox"]').isChecked();
282+
await fillIn('[data-test-id="detail-input"]', 'test detail');
283+
assert.dom('[data-test-id="detail-input"]').hasValue('test detail');
284+
await click('[data-test-id="report-button"]');
285+
286+
assert.dom('[data-test-id="crate-invalid"]').doesNotExist();
287+
assert.dom('[data-test-id="reasons-invalid"]').doesNotExist();
288+
assert.dom('[data-test-id="detail-invalid"]').doesNotExist();
289+
290+
let body = `I'm reporting the https://crates.io/crates/nanomsg crate because:
291+
292+
- [x] it contains spam
293+
- [ ] it is name-squatting (reserving a crate name without content)
294+
- [ ] it is abusive or otherwise harmful
295+
- [ ] it contains a vulnerability (please try to contact the crate author first)
296+
- [x] it is violating the usage policy in some other way (please specify below)
297+
298+
Additional details:
299+
183300
test detail
184301
`;
185302
let subject = `The "nanomsg" crate`;

0 commit comments

Comments
 (0)