Merge pull request #67 from o-development/feat/notification-hook

Add subscription option and test to @ldo/solid-react
main
jaxoncreed 8 months ago committed by GitHub
commit f8fbe56f17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      packages/solid-react/.gitignore
  2. 2
      packages/solid-react/jest.setup.ts
  3. 12
      packages/solid-react/src/useResource.ts
  4. 81
      packages/solid-react/test/Integration.test.tsx
  5. 2
      packages/solid/.gitignore
  6. 2
      packages/solid/test/solidServer.helper.ts

@ -0,0 +1 @@
test/test-server/data

@ -1,2 +1,2 @@
import "@inrupt/jest-jsdom-polyfills";
globalThis.fetch = async () => new Response();
globalThis.fetch = async () => new Response();

@ -11,6 +11,7 @@ import { useLdo } from "./SolidLdoProvider";
export interface UseResourceOptions {
suppressInitialRead?: boolean;
reloadOnMount?: boolean;
subscribe?: boolean;
}
export function useResource(
@ -62,6 +63,17 @@ export function useResource(
{ resource?: Resource; callback: () => void } | undefined
>();
useEffect(() => {
if (options?.subscribe) {
resource?.subscribeToNotifications();
} else {
resource?.unsubscribeFromNotifications();
}
return () => {
resource?.unsubscribeFromNotifications();
};
}, [resource, options?.subscribe]);
// Callback function to force the react dom to reload.
const forceReload = useCallback(
// Wrap the resource in a proxy so it's techically a different object

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import type { FunctionComponent } from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { render, screen, fireEvent, act } from "@testing-library/react";
import {
SAMPLE_BINARY_URI,
SAMPLE_DATA_URI,
@ -131,6 +131,11 @@ describe("Integration Tests", () => {
});
});
/**
* ===========================================================================
* useRootContainer
* ===========================================================================
*/
describe("useRootContainer", () => {
it("gets the root container for a sub-resource", async () => {
const RootContainerTest: FunctionComponent = () => {
@ -169,7 +174,12 @@ describe("Integration Tests", () => {
});
});
describe("useLdoMethod", () => {
/**
* ===========================================================================
* useLdoMethods
* ===========================================================================
*/
describe("useLdoMethods", () => {
it("uses get subject to get a linked data object", async () => {
const GetSubjectTest: FunctionComponent = () => {
const [subject, setSubject] = useState<PostSh | undefined>();
@ -217,6 +227,11 @@ describe("Integration Tests", () => {
});
});
/**
* ===========================================================================
* useSubject
* ===========================================================================
*/
describe("useSubject", () => {
it("renders the article body from the useSubject value", async () => {
const UseSubjectTest: FunctionComponent = () => {
@ -352,5 +367,65 @@ describe("Integration Tests", () => {
);
warn.mockReset();
});
it("rerenders when asked to subscribe to a resource", async () => {
const NotificationTest: FunctionComponent = () => {
const resource = useResource(SAMPLE_DATA_URI, { subscribe: true });
const post = useSubject(PostShShapeType, `${SAMPLE_DATA_URI}#Post1`);
const addPublisher = useCallback(async () => {
await fetch(SAMPLE_DATA_URI, {
method: "PATCH",
body: `INSERT DATA { <${SAMPLE_DATA_URI}#Post1> <http://schema.org/publisher> <https://example.com/Publisher3> . }`,
headers: {
"Content-Type": "application/sparql-update",
},
});
}, []);
if (resource.isLoading() || !post) return <p>loading</p>;
return (
<div>
<ul role="list">
{post.publisher.map((publisher) => {
return <li key={publisher["@id"]}>{publisher["@id"]}</li>;
})}
</ul>
<button onClick={addPublisher}>Add Publisher</button>
</div>
);
};
const { unmount } = render(
<UnauthenticatedSolidLdoProvider>
<NotificationTest />
</UnauthenticatedSolidLdoProvider>,
);
const list = await screen.findByRole("list");
expect(list.children[0].innerHTML).toBe("https://example.com/Publisher1");
expect(list.children[1].innerHTML).toBe("https://example.com/Publisher2");
// Wait for subscription to connect
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
});
// Click button to add a publisher
await fireEvent.click(screen.getByText("Add Publisher"));
await screen.findByText("https://example.com/Publisher3");
// Verify the new publisher is in the list
const updatedList = await screen.findByRole("list");
expect(updatedList.children[2].innerHTML).toBe(
"https://example.com/Publisher3",
);
unmount();
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
});
});
});
});

@ -1 +1 @@
data
test/data

@ -34,7 +34,7 @@ export async function createApp(customConfigPath?: string): Promise<App> {
port: 3_001,
loggingLevel: "off",
seedConfig: path.join(__dirname, "configs", "solid-css-seed.json"),
rootFilePath: "./data",
rootFilePath: path.join(__dirname, "./data"),
},
});
}

Loading…
Cancel
Save