From cf825e6719270df9e0d3d67021f3fd7276b2a6d0 Mon Sep 17 00:00:00 2001 From: Thom van Kalkeren Date: Thu, 23 Sep 2021 20:17:32 +0200 Subject: [PATCH] Soft fail when passing non-term to useAction --- package.json | 1 + src/hooks/__tests__/useAction.spec.ts | 16 ++++++++- src/hooks/useAction.ts | 18 ++++++++-- src/index.ts | 2 +- yarn.lock | 51 +++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5cccbe3..a5ccea0 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@pika/plugin-ts-standard-pkg": "^0.8.1", "@rdfdev/iri": "^1.0.0", "@testing-library/react": "^11.2.6", + "@testing-library/react-hooks": "^7.0.2", "@types/enzyme": "^3.10.5", "@types/enzyme-adapter-react-16": "^1.0.6", "@types/hoist-non-react-statics": "^3.3.1", diff --git a/src/hooks/__tests__/useAction.spec.ts b/src/hooks/__tests__/useAction.spec.ts index dfcbfaf..cc14969 100644 --- a/src/hooks/__tests__/useAction.spec.ts +++ b/src/hooks/__tests__/useAction.spec.ts @@ -1,12 +1,14 @@ import "../../__tests__/useHashFactory"; +import rdf from "@ontologies/core"; +import { renderHook } from "@testing-library/react-hooks"; import React from "react"; import ReactDOM from "react-dom"; import { act } from "react-dom/test-utils"; import * as ctx from "../../__tests__/helpers/fixtures"; import ex from "../../ontology/ex"; -import { useAction } from "../useAction"; +import { NoActionError, useAction } from "../useAction"; describe("useAction", () => { let container: HTMLElement | undefined; @@ -21,6 +23,18 @@ describe("useAction", () => { container = undefined; }); + it("throws when executing undefined", () => { + const { result } = renderHook(() => useAction(undefined)); + + return expect(result.current()).rejects.toThrow(NoActionError); + }); + + it("throws when executing literal", () => { + const { result } = renderHook(() => useAction(rdf.literal("test"))); + + return expect(result.current()).rejects.toThrow(NoActionError); + }); + it("executes by iri", async () => { const opts = ctx.fullCW(); diff --git a/src/hooks/useAction.ts b/src/hooks/useAction.ts index 494ae56..4aac33b 100644 --- a/src/hooks/useAction.ts +++ b/src/hooks/useAction.ts @@ -1,4 +1,4 @@ -import { isNamedNode, NamedNode } from "@ontologies/core"; +import { isNamedNode, SomeTerm } from "@ontologies/core"; import { ActionMap, DataObject } from "link-lib"; import React from "react"; @@ -15,11 +15,22 @@ const findAction = (lrs: LinkReduxLRSType, actionPath: string) => actionPath lrs.actions, ); +export class NoActionError extends Error { + constructor(message?: string | undefined) { + super(message); + this.name = "NoActionError"; + } +} + const createHandler = ( lrs: LinkReduxLRSType, - action: NamedNode | string, + action: SomeTerm | string | undefined, defaultArgs?: DataObject, ) => { + if (typeof action !== "string" && !isNamedNode(action)) { + return () => Promise.reject(new NoActionError(action?.toString())); + } + if (isNamedNode(action)) { return (args?: DataObject) => lrs.exec(action, args ?? defaultArgs); } @@ -34,6 +45,7 @@ const createHandler = ( /** * Returns a handler which executes the {action} from the current store. + * If `action` is `undefined` or a {Literal}, it rejects with {NoActionError}. * * This function uses {exec}, so called handlers will pass through the middleware. * @@ -41,7 +53,7 @@ const createHandler = ( * @param defaultArgs Will be passed if the handler calling site doesn't provide any args. */ export const useAction = ( - action: NamedNode | string, + action: SomeTerm | string | undefined, defaultArgs?: DataObject, ): (args?: DataObject) => Promise => { const lrs = useLRS(); diff --git a/src/index.ts b/src/index.ts index 506ec02..2124c4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,7 @@ export { withTopology } from "./hocs/withTopology"; /* hooks */ -export { useAction, BoundActionHandler } from "./hooks/useAction"; +export { useAction, BoundActionHandler, NoActionError } from "./hooks/useAction"; export { useCalculateChildProps } from "./hooks/useCalculateChildProps"; export { useDataFetching } from "./hooks/useDataFetching"; export { useDataInvalidation } from "./hooks/useDataInvalidation"; diff --git a/yarn.lock b/yarn.lock index 225414c..fedb0be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1368,6 +1368,17 @@ lz-string "^1.4.4" pretty-format "^26.6.2" +"@testing-library/react-hooks@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz#3388d07f562d91e7f2431a4a21b5186062ecfee0" + integrity sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg== + dependencies: + "@babel/runtime" "^7.12.5" + "@types/react" ">=16.9.0" + "@types/react-dom" ">=16.9.0" + "@types/react-test-renderer" ">=16.9.0" + react-error-boundary "^3.1.0" + "@testing-library/react@^11.2.6": version "11.2.6" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.6.tgz#586a23adc63615985d85be0c903f374dab19200b" @@ -1538,6 +1549,13 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== +"@types/react-dom@>=16.9.0": + version "17.0.9" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.9.tgz#441a981da9d7be117042e1a6fd3dac4b30f55add" + integrity sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg== + dependencies: + "@types/react" "*" + "@types/react-dom@^16.9.5": version "16.9.5" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7" @@ -1545,6 +1563,13 @@ dependencies: "@types/react" "*" +"@types/react-test-renderer@>=16.9.0": + version "17.0.1" + resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz#3120f7d1c157fba9df0118dae20cb0297ee0e06b" + integrity sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw== + dependencies: + "@types/react" "*" + "@types/react@*", "@types/react@^16.9.27": version "16.9.27" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.27.tgz#7fc5db99e3ec3f21735b44d3560cff684856814a" @@ -1553,6 +1578,20 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@>=16.9.0": + version "17.0.24" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.24.tgz#7e1b3f78d0fc53782543f9bce6d949959a5880bd" + integrity sha512-eIpyco99gTH+FTI3J7Oi/OH8MZoFMJuztNRimDOJwH4iGIsKV2qkGnk4M9VzlaVWeEEWLWSQRy0FEA0Kz218cg== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -2483,6 +2522,11 @@ csstype@^2.2.0: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== +csstype@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" + integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -5994,6 +6038,13 @@ react-dom@^16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" +react-error-boundary@^3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.3.tgz#276bfa05de8ac17b863587c9e0647522c25e2a0b" + integrity sha512-A+F9HHy9fvt9t8SNDlonq01prnU8AmkjvGKV4kk8seB9kU3xMEO8J/PQlLVmoOIDODl5U2kufSBs4vrWIqhsAA== + dependencies: + "@babel/runtime" "^7.12.5" + react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"