Skip to content

Commit

Permalink
Merge branch 'main' into cve-api
Browse files Browse the repository at this point in the history
  • Loading branch information
ilayda-cp authored Feb 5, 2025
2 parents c36d955 + 33ab674 commit bce6737
Show file tree
Hide file tree
Showing 41 changed files with 504 additions and 529 deletions.
6 changes: 3 additions & 3 deletions static/js/publisher/pages/Builds/LoggedOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function BuildsDefault() {
alt=""
width="343"
height="288"
className="u-hide u-show--small"
className="u-hide--large"
/>
<p>
Start by creating a repo and pushing your code to GitHub. Make
Expand All @@ -55,7 +55,7 @@ function BuildsDefault() {
alt=""
width="343"
height="288"
className="u-hide u-show--small"
className="u-hide--large"
/>
<p>
Register a name on Snapcraft and attach it to your repo to start
Expand All @@ -69,7 +69,7 @@ function BuildsDefault() {
alt=""
width="343"
height="288"
className="u-hide u-show--small"
className="u-hide--large"
/>
<p>
Release your snap to your users. From here on, all the updates you
Expand Down
15 changes: 11 additions & 4 deletions static/js/publisher/pages/Builds/RepoSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,21 @@ function RepoSelector({ githubData, setAutoTriggerBuild }: Props) {
const [reposLoading, setReposLoading] = useState<boolean>(false);
const [validRepo, setValidRepo] = useState<boolean | null>(null);
const [validationError, setValidationError] = useState<boolean>(false);

const getRepoNameWithOwner = (repo: Repo) =>
selectedOrg ? `${selectedOrg}/${repo.name}` : repo.nameWithOwner;

const validateRepo = async (repo: Repo | undefined) => {
if (!repo) {
return;
}

setValidating(true);

const repoName = getRepoNameWithOwner(repo);

const response = await fetch(
`/api/${snapId}/builds/validate-repo?repo=${repo.nameWithOwner}`,
`/api/${snapId}/builds/validate-repo?repo=${repoName}`,
);

if (!response.ok) {
Expand Down Expand Up @@ -93,7 +99,7 @@ function RepoSelector({ githubData, setAutoTriggerBuild }: Props) {
return githubData.github_orgs.map((org) => {
return {
label: org.name,
value: org.name,
value: org.login,
};
});
}
Expand Down Expand Up @@ -156,7 +162,8 @@ function RepoSelector({ githubData, setAutoTriggerBuild }: Props) {
const formData = new FormData();
formData.set("csrf_token", window.CSRF_TOKEN);
if (selectedRepo) {
formData.set("github_repository", selectedRepo.nameWithOwner);
const repoName = getRepoNameWithOwner(selectedRepo);
formData.set("github_repository", repoName);
}

const response = await fetch(`/api/${snapId}/builds`, {
Expand Down Expand Up @@ -185,7 +192,7 @@ function RepoSelector({ githubData, setAutoTriggerBuild }: Props) {
options={[
{ label: "Select organization", value: "" },
{
label: githubData.github_user.name,
label: githubData?.github_user.name,
value: githubData?.github_user.login,
},
...getOrgs(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { BrowserRouter } from "react-router-dom";
import { RecoilRoot } from "recoil";
import { QueryClient, QueryClientProvider } from "react-query";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import "@testing-library/jest-dom";

import CreateSigningKeyForm from "../CreateSigningKeyForm";

const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});

const renderComponent = () => {
return render(
<RecoilRoot>
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<CreateSigningKeyForm
setShowNotification={jest.fn()}
setErrorMessage={jest.fn()}
refetch={jest.fn()}
/>
</QueryClientProvider>
</BrowserRouter>
</RecoilRoot>,
);
};

describe("CreateSigningKeyForm", () => {
it("disables 'Add signing key' button if no new signing key name", async () => {
renderComponent();
expect(
screen.getByRole("button", { name: "Add signing key" }),
).toHaveAttribute("aria-disabled", "true");
});

it("enables 'Add signing key' button if there is a new signing key name", async () => {
const user = userEvent.setup();
renderComponent();
await user.type(
screen.getByRole("textbox", { name: "Signing key name" }),
"test-signing key-name",
);
expect(
screen.getByRole("button", { name: "Add signing key" }),
).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { BrowserRouter } from "react-router-dom";
import { RecoilRoot } from "recoil";
import { QueryClient, QueryClientProvider } from "react-query";
import { render, screen } from "@testing-library/react";

import "@testing-library/jest-dom";

import DeactivateSigningKeyModal from "../DeactivateSigningKeyModal";

const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});

const renderComponent = () => {
return render(
<RecoilRoot>
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<DeactivateSigningKeyModal
setModalOpen={jest.fn()}
handleDisable={jest.fn()}
isDeleting={false}
signingKey={{
name: "test-signing-key",
"created-at": "2025-01-30",
"modified-at": null,
}}
/>
</QueryClientProvider>
</BrowserRouter>
</RecoilRoot>,
);
};

describe("DeactivateSigningKeyModal", () => {
it("Displays correct key in confirmation message", async () => {
renderComponent();
expect(
screen.getByText(
/This will permanently disable the signing key test-signing-key/,
),
).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { BrowserRouter } from "react-router-dom";
import { RecoilRoot } from "recoil";
import { QueryClient, QueryClientProvider } from "react-query";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import "@testing-library/jest-dom";

import SigningKeys from "../SigningKeys";

const mockFilterQuery = "signing key-1";

jest.mock("react-router-dom", () => {
return {
...jest.requireActual("react-router-dom"),
useSearchParams: () => [new URLSearchParams({ filter: mockFilterQuery })],
};
});

const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});

function renderComponent() {
return render(
<RecoilRoot>
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<SigningKeys />
</QueryClientProvider>
</BrowserRouter>
</RecoilRoot>,
);
}

describe("SigningKeys", () => {
it("displays a link to create a new signing key", () => {
renderComponent();
expect(
screen.getByRole("link", { name: "Create new signing key" }),
).toBeInTheDocument();
});

it("shows a create signing key form when 'Create new signing key' button clicked", async () => {
const user = userEvent.setup();
renderComponent();
await user.click(
screen.getByRole("link", { name: "Create new signing key" }),
);
expect(
screen.getByRole("textbox", { name: "Signing key name" }),
).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Add signing key" }),
).toBeInTheDocument();
});

it("displays a filter input", () => {
renderComponent();
expect(screen.getByLabelText("Signing keys")).toBeInTheDocument();
});

it("populates filter with the filter query parameter", () => {
renderComponent();
expect(screen.getByLabelText("Signing keys")).toHaveValue(mockFilterQuery);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { BrowserRouter } from "react-router-dom";
import { RecoilRoot } from "recoil";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";

import SigningKeysTable from "../SigningKeysTable";

const renderComponent = () => {
return render(
<RecoilRoot>
<BrowserRouter>
<SigningKeysTable
setShowDisableSuccessNotification={jest.fn()}
enableTableActions={false}
/>
</BrowserRouter>
</RecoilRoot>,
);
};

describe("SigningKeysTable", () => {
it("renders", () => {
renderComponent();
expect(screen.getByTestId("signing-keys-table")).toBeInTheDocument();
});

it("renders the correct columns", () => {
renderComponent();

expect(
screen.getByRole("columnheader", { name: /Name/ }),
).toBeInTheDocument();

expect(
screen.getByRole("columnheader", { name: "Policies" }),
).toBeInTheDocument();

expect(
screen.getByRole("columnheader", { name: "Models" }),
).toBeInTheDocument();

expect(
screen.getByRole("columnheader", { name: "Created date" }),
).toBeInTheDocument();

expect(
screen.getByRole("columnheader", { name: "fingerprint" }),
).toBeInTheDocument();
});

it("sorts the 'Name' column when clicking the column header", async () => {
renderComponent();

const user = userEvent.setup();
const columnHeader = screen.getByRole("columnheader", { name: /Name/ });

expect(columnHeader.getAttribute("aria-sort")).toBe("none");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("ascending");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("descending");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("none");
});

it("sorts the 'Created date' column when clicking the column header", async () => {
renderComponent();

const user = userEvent.setup();
const columnHeader = screen.getByRole("columnheader", {
name: "Created date",
});

expect(columnHeader.getAttribute("aria-sort")).toBe("none");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("ascending");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("descending");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("none");
});

it("sorts the 'Created date' column when clicking the column header", async () => {
renderComponent();

const user = userEvent.setup();
const columnHeader = screen.getByRole("columnheader", {
name: "Created date",
});

expect(columnHeader.getAttribute("aria-sort")).toBe("none");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("ascending");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("descending");

await user.click(columnHeader);
expect(columnHeader.getAttribute("aria-sort")).toBe("none");
});
});
2 changes: 1 addition & 1 deletion static/js/publisher/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export type ListingData = {
};

export type GithubData = {
github_orgs: { name: string }[];
github_orgs: { name: string; login: string }[];
github_repository: string | null;
github_user: {
avatarUrl: string;
Expand Down
Loading

0 comments on commit bce6737

Please sign in to comment.