Skip to content

Commit

Permalink
Fix links to build artifacts (#443)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabalafou authored Nov 26, 2024
1 parent e0d8cac commit ee5df16
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 32 deletions.
7 changes: 2 additions & 5 deletions src/features/artifacts/components/ArtifactsItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import { useTheme } from "@mui/material/styles";

import { Artifact } from "../../../common/models";
import { PrefContext } from "../../../preferences";
import { artifactBaseUrl } from "../../../utils/helpers";
import { useApiUrl } from "../../../hooks";

interface IArtifactsProps {
/**
Expand All @@ -16,9 +15,7 @@ interface IArtifactsProps {
}

export const ArtifactItem = ({ artifact }: IArtifactsProps) => {
const pref = React.useContext(PrefContext);
const url = artifactBaseUrl(pref.apiUrl, window.location.origin);
const route = new URL(artifact.route, url).toString();
const route = useApiUrl(artifact.route);
const theme = useTheme();

return (
Expand Down
9 changes: 2 additions & 7 deletions src/features/metadata/components/EnvBuildStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ import { CircularProgress, Typography } from "@mui/material";
import Link from "@mui/material/Link";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import { Artifact, Build } from "../../../common/models";
import { PrefContext } from "../../../preferences";
import { StyledMetadataItem } from "../../../styles/StyledMetadataItem";
import artifactList from "../../../utils/helpers/artifact";
import { artifactBaseUrl } from "../../../utils/helpers/parseArtifactList";
import { buildStatus } from "../../../utils/helpers/buildMapper";
import { useApiUrl } from "../../../hooks";

const LogLink = ({ logArtifact }: { logArtifact: Artifact }) => {
const pref = React.useContext(PrefContext);
const url = new URL(
logArtifact.route,
artifactBaseUrl(pref.apiUrl, window.location.origin)
);
const url = useApiUrl(logArtifact.route);
return (
<Link
href={url.toString()}
Expand Down
24 changes: 24 additions & 0 deletions src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
import React from "react";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "./store";
import { PrefContext } from "./preferences";

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

/**
* React Hook to prefix API routes with the base API URL
*
* @param {string} route - A route in the API
* @return {string}
*
* @example
* apiUrl = "/conda-store"
* useApiUrl("api/v1/namespace")
* "/conda-store/api/v1/namespace"
*/
export const useApiUrl = (route: string): string => {
const { apiUrl } = React.useContext(PrefContext);
return (
// remove slash from end (if there is one)
apiUrl.replace(/\/$/, "") +
"/" +
// remove slash from start (if there is one)
route.replace(/^\//, "")
);
};
12 changes: 0 additions & 12 deletions src/utils/helpers/parseArtifactList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,3 @@ export const parseArtifacts = (artifact_list: string[] | undefined) => {
return artifact_list.includes(artifact);
});
};

const isPathAbsolute = (path: string) => {
return new RegExp("^(?:[a-z]+:)?//", "i").test(path);
};

export const artifactBaseUrl = (apiUrl: string, baseUrl: string) => {
if (isPathAbsolute(apiUrl)) {
return apiUrl;
} else {
return `${baseUrl}${apiUrl}`;
}
};
46 changes: 38 additions & 8 deletions test/artifacts/ArtifactsList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { render, screen } from "@testing-library/react";
import { ArtifactList } from "../../src/features/artifacts/components";
import { mockTheme } from "../testutils";
import { PrefContext, prefDefault } from "../../src/preferences";

const ARTIFACTS = [
{
Expand All @@ -12,15 +13,44 @@ const ARTIFACTS = [

describe("<ArtifactList />", () => {
it("should render component", () => {
render(
mockTheme(<ArtifactList artifacts={ARTIFACTS} showArtifacts={true} />)
);

render(mockTheme(<ArtifactList artifacts={ARTIFACTS} />));
expect(screen.getByText("Logs and Artifacts")).toBeInTheDocument();
expect(screen.getByText("Show lockfile")).toBeVisible();
expect(screen.getByText("Show lockfile")).toHaveAttribute(
"href",
"http://localhost:8080/api/v1/build/1/lockfile/"
);
});

for (const [apiUrl, expectedArtifactUrl] of [
[
"http://localhost:8080/conda-store/",
"http://localhost:8080/conda-store/api/v1/build/1/lockfile/"
],
[
"http://localhost:8080/conda-store",
"http://localhost:8080/conda-store/api/v1/build/1/lockfile/"
],
["http://localhost:8080", "http://localhost:8080/api/v1/build/1/lockfile/"],
["/conda-store", "/conda-store/api/v1/build/1/lockfile/"],
["/", "/api/v1/build/1/lockfile/"],
["", "/api/v1/build/1/lockfile/"]
]) {
describe(`with REACT_APP_API_URL set to "${apiUrl}"`, () => {
it(`should render expected artifact URL ${expectedArtifactUrl}`, () => {
render(
mockTheme(
<PrefContext.Provider
value={{
...prefDefault,
apiUrl
}}
>
<ArtifactList artifacts={ARTIFACTS} />
</PrefContext.Provider>
)
);
expect(screen.getByText("Show lockfile")).toHaveAttribute(
"href",
expectedArtifactUrl
);
});
});
}
});

0 comments on commit ee5df16

Please sign in to comment.