From 99c02bdae2199d08d67e967ee621f7cab8f63324 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Sun, 4 Feb 2024 21:40:35 -0500 Subject: [PATCH] All tests except useSubject --- .../src/UnauthenticatedSolidLdoProvider.tsx | 1 + packages/solid-react/src/useLdoMethods.ts | 13 +- packages/solid-react/src/useRootContainer.ts | 11 +- .../solid-react/test/.ldo/post.context.ts | 31 ++++ packages/solid-react/test/.ldo/post.schema.ts | 155 ++++++++++++++++++ .../solid-react/test/.ldo/post.shapeTypes.ts | 19 +++ .../solid-react/test/.ldo/post.typings.ts | 45 +++++ .../solid-react/test/Integration.test.tsx | 101 +++++++++++- packages/solid-react/test/setUpServer.ts | 2 +- .../test/useSubject.integration.test.tsx | 9 + 10 files changed, 379 insertions(+), 8 deletions(-) create mode 100644 packages/solid-react/test/.ldo/post.context.ts create mode 100644 packages/solid-react/test/.ldo/post.schema.ts create mode 100644 packages/solid-react/test/.ldo/post.shapeTypes.ts create mode 100644 packages/solid-react/test/.ldo/post.typings.ts create mode 100644 packages/solid-react/test/useSubject.integration.test.tsx diff --git a/packages/solid-react/src/UnauthenticatedSolidLdoProvider.tsx b/packages/solid-react/src/UnauthenticatedSolidLdoProvider.tsx index 3ff6f99..8f25de1 100644 --- a/packages/solid-react/src/UnauthenticatedSolidLdoProvider.tsx +++ b/packages/solid-react/src/UnauthenticatedSolidLdoProvider.tsx @@ -1,3 +1,4 @@ +/* istanbul ignore file */ import React, { useCallback, useMemo } from "react"; import type { FunctionComponent, PropsWithChildren } from "react"; import type { LoginOptions, SessionInfo } from "./SolidAuthContext"; diff --git a/packages/solid-react/src/useLdoMethods.ts b/packages/solid-react/src/useLdoMethods.ts index ae032ef..d6add4e 100644 --- a/packages/solid-react/src/useLdoMethods.ts +++ b/packages/solid-react/src/useLdoMethods.ts @@ -9,13 +9,18 @@ export interface UseLdoMethods { getSubject( shapeType: ShapeType, subject: string | SubjectNode, - ): Type | Error; + ): Type; createData( shapeType: ShapeType, subject: string | SubjectNode, - ...resources: Resource[] + resource: Resource, + ...additionalResources: Resource[] + ): Type; + changeData( + input: Type, + resource: Resource, + ...additionalResources: Resource[] ): Type; - changeData(input: Type, ...resources: Resource[]): Type; commitData(input: LdoBase): ReturnType; } @@ -35,7 +40,7 @@ export function createUseLdoMethods(dataset: SolidLdoDataset): UseLdoMethods { getSubject( shapeType: ShapeType, subject: string | SubjectNode, - ): Type | Error { + ): Type { return dataset.usingType(shapeType).fromSubject(subject); }, /** diff --git a/packages/solid-react/src/useRootContainer.ts b/packages/solid-react/src/useRootContainer.ts index 92847cb..e32369a 100644 --- a/packages/solid-react/src/useRootContainer.ts +++ b/packages/solid-react/src/useRootContainer.ts @@ -1,8 +1,13 @@ import type { Container, ContainerUri } from "@ldo/solid"; import { useEffect, useState } from "react"; +import type { UseResourceOptions } from "./useResource"; import { useResource } from "./useResource"; import { useLdo } from "./SolidLdoProvider"; -export function useRootContainerFor(uri?: string): Container | undefined { + +export function useRootContainerFor( + uri?: string, + options?: UseResourceOptions, +): Container | undefined { const { getResource } = useLdo(); const [rootContainerUri, setRootContainerUri] = useState< @@ -17,8 +22,10 @@ export function useRootContainerFor(uri?: string): Container | undefined { setRootContainerUri(result.uri); } }); + } else { + setRootContainerUri(undefined); } }, [uri]); - return useResource(rootContainerUri); + return useResource(rootContainerUri, options); } diff --git a/packages/solid-react/test/.ldo/post.context.ts b/packages/solid-react/test/.ldo/post.context.ts new file mode 100644 index 0000000..dafbe33 --- /dev/null +++ b/packages/solid-react/test/.ldo/post.context.ts @@ -0,0 +1,31 @@ +import { ContextDefinition } from "jsonld"; + +/** + * ============================================================================= + * postContext: JSONLD Context for post + * ============================================================================= + */ +export const postContext: ContextDefinition = { + type: { + "@id": "@type", + }, + SocialMediaPosting: "http://schema.org/SocialMediaPosting", + CreativeWork: "http://schema.org/CreativeWork", + Thing: "http://schema.org/Thing", + articleBody: { + "@id": "http://schema.org/articleBody", + "@type": "http://www.w3.org/2001/XMLSchema#string", + }, + uploadDate: { + "@id": "http://schema.org/uploadDate", + "@type": "http://www.w3.org/2001/XMLSchema#date", + }, + image: { + "@id": "http://schema.org/image", + "@type": "@id", + }, + publisher: { + "@id": "http://schema.org/publisher", + "@type": "@id", + }, +}; diff --git a/packages/solid-react/test/.ldo/post.schema.ts b/packages/solid-react/test/.ldo/post.schema.ts new file mode 100644 index 0000000..39e8b63 --- /dev/null +++ b/packages/solid-react/test/.ldo/post.schema.ts @@ -0,0 +1,155 @@ +import { Schema } from "shexj"; + +/** + * ============================================================================= + * postSchema: ShexJ Schema for post + * ============================================================================= + */ +export const postSchema: Schema = { + type: "Schema", + shapes: [ + { + id: "https://example.com/PostSh", + type: "ShapeDecl", + shapeExpr: { + type: "Shape", + expression: { + type: "EachOf", + expressions: [ + { + type: "TripleConstraint", + predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + valueExpr: { + type: "NodeConstraint", + values: [ + "http://schema.org/SocialMediaPosting", + "http://schema.org/CreativeWork", + "http://schema.org/Thing", + ], + }, + }, + { + type: "TripleConstraint", + predicate: "http://schema.org/articleBody", + valueExpr: { + type: "NodeConstraint", + datatype: "http://www.w3.org/2001/XMLSchema#string", + }, + min: 0, + max: 1, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#label", + object: { + value: "articleBody", + }, + }, + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: "The actual body of the article. ", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://schema.org/uploadDate", + valueExpr: { + type: "NodeConstraint", + datatype: "http://www.w3.org/2001/XMLSchema#date", + }, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#label", + object: { + value: "uploadDate", + }, + }, + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: + "Date when this media object was uploaded to this site.", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://schema.org/image", + valueExpr: { + type: "NodeConstraint", + nodeKind: "iri", + }, + min: 0, + max: 1, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#label", + object: { + value: "image", + }, + }, + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: + "A media object that encodes this CreativeWork. This property is a synonym for encoding.", + }, + }, + ], + }, + { + type: "TripleConstraint", + predicate: "http://schema.org/publisher", + valueExpr: { + type: "NodeConstraint", + nodeKind: "iri", + }, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#label", + object: { + value: "publisher", + }, + }, + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: "The publisher of the creative work.", + }, + }, + ], + }, + ], + }, + annotations: [ + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#label", + object: { + value: "SocialMediaPost", + }, + }, + { + type: "Annotation", + predicate: "http://www.w3.org/2000/01/rdf-schema#comment", + object: { + value: + "A post to a social media platform, including blog posts, tweets, Facebook posts, etc.", + }, + }, + ], + }, + }, + ], +}; diff --git a/packages/solid-react/test/.ldo/post.shapeTypes.ts b/packages/solid-react/test/.ldo/post.shapeTypes.ts new file mode 100644 index 0000000..4c50683 --- /dev/null +++ b/packages/solid-react/test/.ldo/post.shapeTypes.ts @@ -0,0 +1,19 @@ +import { ShapeType } from "@ldo/ldo"; +import { postSchema } from "./post.schema"; +import { postContext } from "./post.context"; +import { PostSh } from "./post.typings"; + +/** + * ============================================================================= + * LDO ShapeTypes post + * ============================================================================= + */ + +/** + * PostSh ShapeType + */ +export const PostShShapeType: ShapeType = { + schema: postSchema, + shape: "https://example.com/PostSh", + context: postContext, +}; diff --git a/packages/solid-react/test/.ldo/post.typings.ts b/packages/solid-react/test/.ldo/post.typings.ts new file mode 100644 index 0000000..9ebaf71 --- /dev/null +++ b/packages/solid-react/test/.ldo/post.typings.ts @@ -0,0 +1,45 @@ +import { ContextDefinition } from "jsonld"; + +/** + * ============================================================================= + * Typescript Typings for post + * ============================================================================= + */ + +/** + * PostSh Type + */ +export interface PostSh { + "@id"?: string; + "@context"?: ContextDefinition; + type: + | { + "@id": "SocialMediaPosting"; + } + | { + "@id": "CreativeWork"; + } + | { + "@id": "Thing"; + }; + /** + * The actual body of the article. + */ + articleBody?: string; + /** + * Date when this media object was uploaded to this site. + */ + uploadDate: string; + /** + * A media object that encodes this CreativeWork. This property is a synonym for encoding. + */ + image?: { + "@id": string; + }; + /** + * The publisher of the creative work. + */ + publisher: { + "@id": string; + }; +} diff --git a/packages/solid-react/test/Integration.test.tsx b/packages/solid-react/test/Integration.test.tsx index f842781..e224a35 100644 --- a/packages/solid-react/test/Integration.test.tsx +++ b/packages/solid-react/test/Integration.test.tsx @@ -1,9 +1,18 @@ import React, { useEffect, useState } from "react"; import type { FunctionComponent } from "react"; import { render, screen, fireEvent } from "@testing-library/react"; -import { SAMPLE_BINARY_URI, SAMPLE_DATA_URI, setUpServer } from "./setUpServer"; +import { + SAMPLE_BINARY_URI, + SAMPLE_DATA_URI, + SERVER_DOMAIN, + setUpServer, +} from "./setUpServer"; import { UnauthenticatedSolidLdoProvider } from "../src/UnauthenticatedSolidLdoProvider"; import { useResource } from "../src/useResource"; +import { useRootContainerFor } from "../src/useRootContainer"; +import { useLdo } from "../src/SolidLdoProvider"; +import { PostShShapeType } from "./.ldo/post.shapeTypes"; +import type { PostSh } from "./.ldo/post.typings"; // Use an increased timeout, since the CSS server takes too much setup time. jest.setTimeout(40_000); @@ -118,4 +127,94 @@ describe("Integration Tests", () => { expect(resourceStatus2.innerHTML).toBe("binaryReadSuccess"); }); }); + + describe("useRootContainer", () => { + it("gets the root container for a sub-resource", async () => { + const RootContainerTest: FunctionComponent = () => { + const rootContainer = useRootContainerFor(SAMPLE_DATA_URI, { + suppressInitialRead: true, + }); + return rootContainer ? ( +

{rootContainer?.uri}

+ ) : undefined; + }; + render( + + + , + ); + const container = await screen.findByRole("root"); + expect(container.innerHTML).toBe(SERVER_DOMAIN); + }); + + it("returns undefined when a URI is not provided", async () => { + const RootContainerTest: FunctionComponent = () => { + const rootContainer = useRootContainerFor(undefined, { + suppressInitialRead: true, + }); + return rootContainer ? ( +

{rootContainer?.uri}

+ ) : ( +

Undefined

+ ); + }; + render( + + + , + ); + const container = await screen.findByRole("undefined"); + expect(container.innerHTML).toBe("Undefined"); + }); + }); + + describe("useLdoMethod", () => { + it("uses get subject to get a linked data object", async () => { + const GetSubjectTest: FunctionComponent = () => { + const [subject, setSubject] = useState(); + const { getSubject } = useLdo(); + useEffect(() => { + const someSubject = getSubject( + PostShShapeType, + "https://example.com/subject", + ); + setSubject(someSubject); + }, []); + return subject ?

{subject["@id"]}

: undefined; + }; + render( + + + , + ); + const container = await screen.findByRole("subject"); + expect(container.innerHTML).toBe("https://example.com/subject"); + }); + + it("uses createData to create a new data object", async () => { + const GetSubjectTest: FunctionComponent = () => { + const [subject, setSubject] = useState(); + const { createData, getResource } = useLdo(); + useEffect(() => { + const someSubject = createData( + PostShShapeType, + "https://example.com/subject", + getResource("https://example.com/"), + ); + someSubject.articleBody = "Cool Article"; + setSubject(someSubject); + }, []); + return subject ? ( +

{subject.articleBody}

+ ) : undefined; + }; + render( + + + , + ); + const container = await screen.findByRole("subject"); + expect(container.innerHTML).toBe("Cool Article"); + }); + }); }); diff --git a/packages/solid-react/test/setUpServer.ts b/packages/solid-react/test/setUpServer.ts index a3e4f4a..57fabee 100644 --- a/packages/solid-react/test/setUpServer.ts +++ b/packages/solid-react/test/setUpServer.ts @@ -73,7 +73,7 @@ export function setUpServer(): SetUpServerReturn { beforeEach(async () => { s.fetchMock = jest.fn(s.authFetch); // Create a new document called sample.ttl - const result = await s.authFetch(ROOT_CONTAINER, { + await s.authFetch(ROOT_CONTAINER, { method: "POST", headers: { link: '; rel="type"', diff --git a/packages/solid-react/test/useSubject.integration.test.tsx b/packages/solid-react/test/useSubject.integration.test.tsx new file mode 100644 index 0000000..6aaf84f --- /dev/null +++ b/packages/solid-react/test/useSubject.integration.test.tsx @@ -0,0 +1,9 @@ +import { setUpServer } from "./setUpServer"; + +describe("useSubject", () => { + setUpServer(); + + it("trivial", () => { + expect(true).toBe(true); + }); +});