diff --git a/components/Grid/Item.test.tsx b/components/Grid/Item.test.tsx
index ebe6bd41..cddc838d 100644
--- a/components/Grid/Item.test.tsx
+++ b/components/Grid/Item.test.tsx
@@ -1,6 +1,9 @@
import { render, screen } from "@/test-utils";
import GridItem from "./Item";
+import React from "react";
import { SearchShape } from "@/types/api/response";
+import { UserContext } from "@/context/user-context";
+import { UserContext as UserContextType } from "@/types/context/user";
const mockItem = {
api_model: "Work",
@@ -21,6 +24,28 @@ const mockItem = {
work_type: "Image",
};
+const defaultUserContext: UserContextType = {
+ user: {
+ isInstitution: false,
+ isLoggedIn: false,
+ isReadingRoom: false,
+ scopes: ["read:Public", "read:Published"],
+ },
+ isLoading: false,
+ isSignInModalOpen: false,
+ openSignInModal: jest.fn(),
+ closeSignInModal: jest.fn(),
+};
+
+const withUserProvider = (
+ Component: React.ReactNode,
+ userContext: UserContextType = defaultUserContext,
+) => {
+ return (
+ {Component}
+ );
+};
+
describe("GridItem component", () => {
it("renders the item, link and image", () => {
render();
@@ -50,4 +75,51 @@ describe("GridItem component", () => {
"https://iiif.stack.rdc-staging.library.northwestern.edu/iiif/2/b92874a0-72b7-4479-979e-38860c412a13/square/512,/0/default.jpg",
);
});
+
+ it("does not render a lock for public items when auth finishes without a user", () => {
+ render(
+ withUserProvider(, {
+ ...defaultUserContext,
+ user: null,
+ }),
+ );
+
+ expect(screen.queryByTitle("Restricted Item")).not.toBeInTheDocument();
+ });
+
+ it("renders a lock for non-public items while auth is loading", () => {
+ const institutionItem = {
+ ...mockItem,
+ visibility: "Institution",
+ };
+
+ render(
+ withUserProvider(, {
+ ...defaultUserContext,
+ isLoading: true,
+ user: null,
+ }),
+ );
+
+ expect(screen.getByTitle("Restricted Item")).toBeInTheDocument();
+ });
+
+ it("does not render a lock for non-public items when the user has the matching scope", () => {
+ const institutionItem = {
+ ...mockItem,
+ visibility: "Institution",
+ };
+
+ render(
+ withUserProvider(, {
+ ...defaultUserContext,
+ user: {
+ ...defaultUserContext.user!,
+ scopes: ["read:Public", "read:Published", "read:Institution"],
+ },
+ }),
+ );
+
+ expect(screen.queryByTitle("Restricted Item")).not.toBeInTheDocument();
+ });
});
diff --git a/components/Grid/Item.tsx b/components/Grid/Item.tsx
index cf12f1b2..14090d2d 100644
--- a/components/Grid/Item.tsx
+++ b/components/Grid/Item.tsx
@@ -16,7 +16,9 @@ const GridItem: React.FC = ({ item, isFeatured }) => {
const userContext = useContext(UserContext);
const isRestricted = (item: SearchShape): boolean => {
- if (userContext?.isLoading) return item?.visibility !== "Public";
+ if (item?.visibility === "Public") return false;
+ if (userContext?.isLoading) return true;
+
return !(
userContext?.user?.scopes?.includes(`read:${item?.visibility}`) ?? false
);
diff --git a/components/Search/TranscriptionResults.test.tsx b/components/Search/TranscriptionResults.test.tsx
new file mode 100644
index 00000000..a8305b40
--- /dev/null
+++ b/components/Search/TranscriptionResults.test.tsx
@@ -0,0 +1,136 @@
+import { render, screen } from "@/test-utils";
+import React from "react";
+import TranscriptionResults from "@/components/Search/TranscriptionResults";
+import { FileSetSearchResult, Pagination } from "@/types/api/response";
+import { UserContext } from "@/context/user-context";
+import { UserContext as UserContextType } from "@/types/context/user";
+
+jest.mock("@/lib/constants/endpoints", () => ({
+ DCAPI_ENDPOINT: "https://dcapi.rdc-staging.library.northwestern.edu/api/v2",
+}));
+
+const defaultUserContext: UserContextType = {
+ user: {
+ isInstitution: false,
+ isLoggedIn: false,
+ isReadingRoom: false,
+ scopes: ["read:Public", "read:Published"],
+ },
+ isLoading: false,
+ isSignInModalOpen: false,
+ openSignInModal: jest.fn(),
+ closeSignInModal: jest.fn(),
+};
+
+const pagination: Pagination = {
+ query_url:
+ "https://dcapi.rdc-staging.library.northwestern.edu/api/v2/search/file-sets?searchToken=N4IgRg9gJgniBcoDOBLAXgUwQFgAwBoQB9JCAVwC&page=1",
+ current_page: 1,
+ limit: 10,
+ offset: 0,
+ total_hits: 1,
+ total_pages: 1,
+ collapsed_by: {
+ field: "work_id",
+ total_hits: 1,
+ },
+};
+
+const publicResult: FileSetSearchResult = {
+ id: "file-set-public",
+ label: "Page 1",
+ work_id: "work-public",
+ work_title: "Public Work",
+ collection: { id: "collection-1", title: "Collection" },
+ rank: 1,
+ annotations: [
+ {
+ id: "annotation-1",
+ type: "transcription",
+ content: "This transcript contains a public match.",
+ language: ["eng"],
+ model: "Transcription",
+ },
+ ],
+ representative_image_url:
+ "https://iiif.stack.rdc-staging.library.northwestern.edu/iiif/2/file-set-public",
+ accession_number: "abc",
+ visibility: "Public",
+};
+
+const withUserProvider = (
+ Component: React.ReactNode,
+ userContext: UserContextType = defaultUserContext,
+) => {
+ return (
+ {Component}
+ );
+};
+
+const renderTranscriptionResults = (
+ results: FileSetSearchResult[],
+ userContext: UserContextType = defaultUserContext,
+) => {
+ return render(
+ withUserProvider(
+ ,
+ userContext,
+ ),
+ );
+};
+
+describe("TranscriptionResults component", () => {
+ it("does not render locks for public file sets when auth finishes without a user", () => {
+ renderTranscriptionResults([publicResult], {
+ ...defaultUserContext,
+ user: null,
+ });
+
+ expect(screen.queryByTitle("Restricted Item")).not.toBeInTheDocument();
+ });
+
+ it("renders locks for non-public file sets while auth is loading", () => {
+ renderTranscriptionResults(
+ [
+ {
+ ...publicResult,
+ id: "file-set-institution",
+ visibility: "Institution",
+ },
+ ],
+ {
+ ...defaultUserContext,
+ isLoading: true,
+ user: null,
+ },
+ );
+
+ expect(screen.getAllByTitle("Restricted Item")).toHaveLength(2);
+ });
+
+ it("does not render locks for non-public file sets when the user has the matching scope", () => {
+ renderTranscriptionResults(
+ [
+ {
+ ...publicResult,
+ id: "file-set-institution",
+ visibility: "Institution",
+ },
+ ],
+ {
+ ...defaultUserContext,
+ user: {
+ ...defaultUserContext.user!,
+ scopes: ["read:Public", "read:Published", "read:Institution"],
+ },
+ },
+ );
+
+ expect(screen.queryByTitle("Restricted Item")).not.toBeInTheDocument();
+ });
+});
diff --git a/components/Search/TranscriptionResults.tsx b/components/Search/TranscriptionResults.tsx
index 5df61160..299ea1d2 100644
--- a/components/Search/TranscriptionResults.tsx
+++ b/components/Search/TranscriptionResults.tsx
@@ -81,7 +81,9 @@ const TranscriptionResults: React.FC = ({
const groups = groupByWork(results);
const { user, isLoading } = useContext(UserContext);
const isRestricted = (visibility: string) => {
- if (isLoading) return visibility !== "Public";
+ if (visibility === "Public") return false;
+ if (isLoading) return true;
+
return !(user?.scopes?.includes(`read:${visibility}`) ?? false);
};