Skip to content

Commit e9d4772

Browse files
authored
WD-21811 - snap icon causes Internal Server Error (#5118)
* Fix PreviewForm data not being refreshed * Fix Internal Server Error when previewing blob image * Add unit tests for listing page * Fix htmlFor fields and add a missing id * Fix added unit tests * Increased timeout for long running unit test
1 parent fd2a3f4 commit e9d4772

17 files changed

Lines changed: 844 additions & 250 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { render, screen } from "@testing-library/react";
2+
import "@testing-library/jest-dom";
3+
4+
import { mockListingData } from "../../../../test-utils";
5+
import AdditionalInformation from "../AdditionalInformation";
6+
import { FieldValues, useForm } from "react-hook-form";
7+
import { getDefaultListingData } from "../../../../utils";
8+
9+
function TestAdditionalInformation() {
10+
const { register, setValue, watch, getValues } = useForm<FieldValues>({
11+
defaultValues: getDefaultListingData(mockListingData),
12+
});
13+
14+
return (
15+
<form>
16+
<AdditionalInformation
17+
data={mockListingData}
18+
register={register}
19+
getValues={getValues}
20+
setValue={setValue}
21+
watch={watch}
22+
/>
23+
</form>
24+
);
25+
}
26+
27+
function renderComponent() {
28+
window.SNAP_LISTING_DATA = {
29+
DNS_VERIFICATION_TOKEN: "test-dns-verification-token",
30+
};
31+
32+
return render(<TestAdditionalInformation />);
33+
}
34+
35+
afterEach(() => {
36+
jest.clearAllMocks();
37+
});
38+
39+
describe("AdditionalInformation", () => {
40+
test("LicenseInputs is rendered", () => {
41+
renderComponent();
42+
expect(screen.getByText("License:")).toBeVisible();
43+
expect(screen.getByLabelText("Simple")).toBeVisible();
44+
});
45+
46+
test("Fields displayed and registered with useForm", () => {
47+
renderComponent();
48+
expect(
49+
screen.getByLabelText("Display public popularity charts"),
50+
).toBeVisible();
51+
expect(screen.getByLabelText("World map")).toBeVisible();
52+
expect(screen.getByLabelText("Linux distributions")).toBeVisible();
53+
});
54+
55+
test("if public metrics is unchecked all other fields are disabled", () => {
56+
renderComponent();
57+
expect(
58+
screen.getByRole("checkbox", {
59+
name: "Display public popularity charts",
60+
}),
61+
).not.toBeChecked();
62+
expect(screen.getByRole("checkbox", { name: "World map" })).toBeDisabled();
63+
expect(
64+
screen.getByRole("checkbox", { name: "Linux distributions" }),
65+
).toBeDisabled();
66+
});
67+
});
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { render, screen } from "@testing-library/react";
2+
import userEvent from "@testing-library/user-event";
3+
import "@testing-library/jest-dom";
4+
5+
import { mockListingData } from "../../../../test-utils";
6+
import LicenseInputs from "../LicenseInputs";
7+
import LicenseSearch from "../LicenseSearch";
8+
import { FieldValues, useForm } from "react-hook-form";
9+
import { getDefaultListingData } from "../../../../utils";
10+
11+
jest.mock("../LicenseSearch");
12+
13+
function TestLicenseInputs() {
14+
const { register, setValue, watch } = useForm<FieldValues>({
15+
defaultValues: getDefaultListingData(mockListingData),
16+
});
17+
18+
return (
19+
<form>
20+
<LicenseInputs
21+
listingData={mockListingData}
22+
register={register}
23+
setValue={setValue}
24+
watch={watch}
25+
/>
26+
</form>
27+
);
28+
}
29+
30+
function renderComponent() {
31+
window.SNAP_LISTING_DATA = {
32+
DNS_VERIFICATION_TOKEN: "test-dns-verification-token",
33+
};
34+
35+
return render(<TestLicenseInputs />);
36+
}
37+
38+
afterEach(() => {
39+
jest.clearAllMocks();
40+
});
41+
42+
describe("LicenseInputs", () => {
43+
test("if license is simple the search is displayed", () => {
44+
renderComponent();
45+
expect(screen.getByLabelText("Simple")).toBeChecked();
46+
expect(screen.getByText(/^The license\(s\) under which/)).toBeVisible();
47+
expect(LicenseSearch).toHaveBeenCalled();
48+
});
49+
50+
test("when switching license type to custom a textarea is displayed", async () => {
51+
renderComponent();
52+
const user = userEvent.setup();
53+
54+
expect(screen.getByLabelText("Simple")).toBeChecked();
55+
await user.click(screen.getByLabelText("Custom SPDX expression"));
56+
expect(
57+
await screen.findByLabelText("Custom SPDX expression"),
58+
).toBeChecked();
59+
expect(document.getElementsByTagName("textarea")).toHaveLength(1);
60+
});
61+
});
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { render, screen, waitFor } from "@testing-library/react";
2+
import userEvent from "@testing-library/user-event";
3+
import "@testing-library/jest-dom";
4+
5+
import { mockListingData } from "../../../../test-utils";
6+
import LicenseInputs from "../LicenseInputs";
7+
import { FieldValues, useForm } from "react-hook-form";
8+
import { getDefaultListingData } from "../../../../utils";
9+
10+
function TestLicenseSearch() {
11+
const { register, setValue, watch } = useForm<FieldValues>({
12+
defaultValues: getDefaultListingData(mockListingData),
13+
});
14+
15+
return (
16+
<form>
17+
<LicenseInputs
18+
listingData={mockListingData}
19+
register={register}
20+
setValue={setValue}
21+
watch={watch}
22+
/>
23+
</form>
24+
);
25+
}
26+
27+
function renderComponent() {
28+
window.SNAP_LISTING_DATA = {
29+
DNS_VERIFICATION_TOKEN: "test-dns-verification-token",
30+
};
31+
32+
return render(<TestLicenseSearch />);
33+
}
34+
35+
afterEach(() => {
36+
jest.clearAllMocks();
37+
});
38+
39+
describe("LicenseSearch", () => {
40+
test("the search field displays the currently selected license", () => {
41+
renderComponent();
42+
expect(screen.getByText("testing-license")).toBeVisible();
43+
});
44+
45+
test("click on search field opens list of licenses", async () => {
46+
renderComponent();
47+
const user = userEvent.setup();
48+
await user.click(
49+
document.getElementsByClassName("p-multiselect__input").item(0)!,
50+
);
51+
52+
await waitFor(() => {
53+
const suggestionsElem = document.getElementsByClassName(
54+
"p-list",
55+
)[0]! as HTMLUListElement;
56+
expect(suggestionsElem).toBeVisible();
57+
for (const child of suggestionsElem.children) {
58+
const text = child.textContent;
59+
// the current license should be filtered and not displayed in the dropdown
60+
expect(text).not.toEqual("testing-license");
61+
}
62+
});
63+
});
64+
65+
test("removing focus from search field closes the licenses list", async () => {
66+
const { container } = renderComponent();
67+
const user = userEvent.setup();
68+
await user.click(
69+
document.getElementsByClassName("p-multiselect__input").item(0)!,
70+
);
71+
72+
expect(await screen.findByText("random-license")).toBeVisible();
73+
await user.click(container);
74+
const randomLicense = screen.queryByText("random-license");
75+
expect(randomLicense).toBeNull();
76+
});
77+
78+
test("remove license from list", async () => {
79+
renderComponent();
80+
const user = userEvent.setup();
81+
await user.click(screen.getByRole("button"));
82+
83+
const removedElem = screen.queryByText(/testing-license/);
84+
expect(removedElem).toBeNull();
85+
});
86+
});

static/js/publisher/pages/Listing/ContactInformation/ContactFields.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ function ContactFields({
5858
<Col size={5} emptyLarge={index === 0 ? undefined : 3}>
5959
<div className="p-form__control">
6060
<input
61+
id={fieldName}
6162
type="url"
6263
{...register(`${fieldName}.${index}.url`)}
6364
defaultValue={getValues(`${fieldName}.${index}.url`)}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { FieldValues, useForm } from "react-hook-form";
2+
import { render, screen, waitFor } from "@testing-library/react";
3+
import "@testing-library/jest-dom";
4+
5+
import ContactFields from "../ContactFields";
6+
import userEvent from "@testing-library/user-event";
7+
import { getDefaultListingData } from "../../../../utils";
8+
import { mockListingData } from "../../../../test-utils";
9+
10+
function TestContactFields() {
11+
const { register, getValues, control } = useForm<FieldValues>({
12+
defaultValues: getDefaultListingData(mockListingData),
13+
});
14+
15+
return (
16+
<form>
17+
<ContactFields
18+
register={register}
19+
control={control}
20+
labelName={"Contacts"}
21+
fieldName={"contacts"}
22+
getValues={getValues}
23+
/>
24+
</form>
25+
);
26+
}
27+
28+
function renderComponent() {
29+
window.SNAP_LISTING_DATA = {
30+
DNS_VERIFICATION_TOKEN: "test-dns-verification-token",
31+
};
32+
33+
return render(<TestContactFields />);
34+
}
35+
36+
describe("ContactFields", () => {
37+
test("data displayed and add field at the bottom", () => {
38+
renderComponent();
39+
40+
const fieldElement = screen.getByDisplayValue(
41+
"https://example.com/contact",
42+
);
43+
const addFieldElement = screen.getByText(/Add field/);
44+
45+
expect(fieldElement).toBeVisible();
46+
expect(addFieldElement).toBeVisible();
47+
expect(fieldElement.compareDocumentPosition(addFieldElement)).toEqual(
48+
Node.DOCUMENT_POSITION_FOLLOWING,
49+
);
50+
});
51+
52+
test("data can be removed", async () => {
53+
const user = userEvent.setup();
54+
renderComponent();
55+
56+
const deleteButton = screen.getByRole("button", {
57+
name: "Remove this link",
58+
});
59+
expect(deleteButton).toBeVisible();
60+
61+
await user.click(deleteButton);
62+
await waitFor(() => {
63+
const links = screen.queryAllByRole("textbox");
64+
expect(links).toHaveLength(0);
65+
});
66+
});
67+
68+
test("data can be added", async () => {
69+
const user = userEvent.setup();
70+
renderComponent();
71+
72+
const addButton = screen.getByText(/Add field/);
73+
await user.click(addButton);
74+
await waitFor(() => {
75+
const links = screen.queryAllByRole("textbox");
76+
expect(links).toHaveLength(2);
77+
});
78+
});
79+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { FieldValues, useForm } from "react-hook-form";
2+
import { render, screen } from "@testing-library/react";
3+
import "@testing-library/jest-dom";
4+
5+
import ContactInformation from "../ContactInformation";
6+
import { mockListingData } from "../../../../test-utils";
7+
import { QueryClient, QueryClientProvider } from "react-query";
8+
import { getDefaultListingData } from "../../../../utils";
9+
10+
function TestContactInformation() {
11+
const { register, control, getFieldState, getValues } = useForm<FieldValues>({
12+
defaultValues: getDefaultListingData(mockListingData),
13+
});
14+
15+
const queryClient = new QueryClient();
16+
17+
return (
18+
<QueryClientProvider client={queryClient}>
19+
<form>
20+
<ContactInformation
21+
data={mockListingData}
22+
register={register}
23+
control={control}
24+
getFieldState={getFieldState}
25+
getValues={getValues}
26+
/>
27+
</form>
28+
</QueryClientProvider>
29+
);
30+
}
31+
32+
function renderComponent() {
33+
window.SNAP_LISTING_DATA = {
34+
DNS_VERIFICATION_TOKEN: "test-dns-verification-token",
35+
};
36+
37+
return render(<TestContactInformation />);
38+
}
39+
40+
describe("ContactInformation", () => {
41+
test("all fields are displayed", () => {
42+
renderComponent();
43+
expect(screen.getByLabelText(/^Primary website/)).toBeVisible();
44+
expect(screen.getByLabelText(/^Other websites/)).toBeVisible();
45+
expect(screen.getByLabelText(/^Contacts/)).toBeVisible();
46+
expect(screen.getByLabelText(/^Donations/)).toBeVisible();
47+
expect(screen.getByLabelText(/^Source code/)).toBeVisible();
48+
expect(screen.getByLabelText(/^Issues/)).toBeVisible();
49+
});
50+
});

static/js/publisher/pages/Listing/ListingDetails/ListingDetails.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ function ListingDetails({
241241

242242
<Row className="p-form__group" data-tour="listing-summary">
243243
<Col size={2}>
244-
<label htmlFor="video_urls">Summary:</label>
244+
<label htmlFor="summary">Summary:</label>
245245
</Col>
246246
<Col size={8}>
247247
<div className="p-form__control">
@@ -257,7 +257,7 @@ function ListingDetails({
257257

258258
<Row className="p-form__group" data-tour="listing-description">
259259
<Col size={2}>
260-
<label htmlFor="video_urls">Description:</label>
260+
<label htmlFor="description">Description:</label>
261261
</Col>
262262
<Col size={8}>
263263
<div className="p-form__control">

0 commit comments

Comments
 (0)