diff --git a/core/bsconfig.json b/core/bsconfig.json index a5fbc44a..d35a3c1b 100644 --- a/core/bsconfig.json +++ b/core/bsconfig.json @@ -16,6 +16,7 @@ "react-jsx": 3 }, "suffix": ".bs.js", - "bs-dependencies": ["@rescript/react"], + "bs-dependencies": ["@rescript/react", "@greenlabs/rescript-jest"], + "bs-dev-dependencies": ["@greenlabs/rescript-jest"], "ppx-flags": ["@greenlabs/ppx-ts/ppx"] } diff --git a/core/package.json b/core/package.json index b9a99ca1..aa86564f 100644 --- a/core/package.json +++ b/core/package.json @@ -16,7 +16,8 @@ "@babel/core": "7.17.5", "@emotion/css": "11.10.0", "@emotion/jest": "11.9.3", - "@greenlabs/ppx-ts": "^0.1.6", + "@greenlabs/ppx-ts": "0.1.6", + "@greenlabs/rescript-jest": "^1.0.1", "@rescript/react": "0.10.3", "@storybook/addon-actions": "6.5.9", "@storybook/addon-essentials": "6.5.9", @@ -24,7 +25,7 @@ "@storybook/addon-links": "6.5.9", "@storybook/react": "6.5.9", "@storybook/testing-library": "0.0.13", - "@testing-library/react-hooks": "^8.0.1", + "@testing-library/react-hooks": "8.0.1", "babel-loader": "8.2.3", "jest": "27.2.5", "jsdom": "20.0.0", @@ -34,6 +35,7 @@ "rescript": "10.0.1" }, "peerDependencies": { + "@greenlabs/ppx-ts": ">=0.1.6", "@rescript/react": ">=0.10.0", "react": ">=16.8.0", "react-dom": ">=16.8.0", diff --git a/core/src/bindings/Ancestor_Jest.res b/core/src/bindings/Ancestor_Jest.res deleted file mode 100644 index 53e6a41f..00000000 --- a/core/src/bindings/Ancestor_Jest.res +++ /dev/null @@ -1,69 +0,0 @@ -type testable<'a> -type jestFn - -// lifecycle -@val external afterEach: ((. unit) => unit) => unit = "afterEach" -@val external beforeEach: ((. unit) => unit) => unit = "beforeEach" - -// Methods -@val external describe: (string, (. unit) => unit) => unit = "describe" -@val external it: (string, (. unit) => unit) => unit = "it" -@val external test: (string, (. unit) => unit) => unit = "test" - -// Expect -@val external expect: 'value => testable<'value> = "expect" -@val external expectFn: jestFn => testable<'value> = "expect" -@val external expectArray: array<'value> => testable<'value> = "expect" - -@send external toBe: (testable<'value>, 'value) => unit = "toBe" -@send external toEqual: (testable<'value>, 'value) => testable<'value> = "toEqual" -@send external toContain: (testable<'value>, 'value) => testable<'value> = "toContain" -@send external toHaveBeenCalled: (testable<'value>, unit) => testable<'value> = "toHaveBeenCalled" -@send -external toHaveBeenCalledTimes: (testable<'value>, int) => testable<'value> = - "toHaveBeenCalledTimes" -@send external toMatchSnapshot: testable<'value> => unit = "toMatchSnapshot" - -type spy - -@val @scope("jest") external spyOnWithMethodName: ('a, string, string) => spy = "spyOn" -@send external mockImplementation: (spy, (. unit) => 'a) => unit = "mockImplementation" -@send external mockRestore: (spy, unit) => unit = "mockRestore" - -// .resolves -// .rejects -// .toHaveBeenCalled() -// .toHaveBeenCalledTimes(number) -// .toHaveBeenCalledWith(arg1, arg2, ...) -// .toHaveBeenLastCalledWith(arg1, arg2, ...) -// .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....) -// .toHaveReturned() -// .toHaveReturnedTimes(number) -// .toHaveReturnedWith(value) -// .toHaveLastReturnedWith(value) -// .toHaveNthReturnedWith(nthCall, value) -// .toHaveLength(number) -// .toHaveProperty(keyPath, value?) -// .toBeCloseTo(number, numDigits?) -// .toBeDefined() -// .toBeFalsy() -// .toBeGreaterThan(number | bigint) -// .toBeGreaterThanOrEqual(number | bigint) -// .toBeLessThan(number | bigint) -// .toBeLessThanOrEqual(number | bigint) -// .toBeInstanceOf(Class) -// .toBeNull() -// .toBeTruthy() -// .toBeUndefined() -// .toBeNaN() -// .toContain(item) -// .toContainEqual(item) -// .toMatch(regexp | string) -// .toMatchObject(object) -// .toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot) -// .toStrictEqual(value) -// .toThrow(error?) -// .toThrowErrorMatchingSnapshot(hint?) -// .toThrowErrorMatchingInlineSnapshot(inlineSnapshot) - -@get external not: testable<'value> => testable<'value> = "not" diff --git a/core/src/components/box/Ancestor_Box_Test.res b/core/src/components/box/Ancestor_Box_Test.res index 1c8e2a15..fbf73990 100644 --- a/core/src/components/box/Ancestor_Box_Test.res +++ b/core/src/components/box/Ancestor_Box_Test.res @@ -1,9 +1,10 @@ -open Ancestor_Jest +open Jest +open Expect open Ancestor module Renderer = Ancestor_ReactTestRenderer -describe("Box", (. ()) => { - it("should render with columns correctly", (. ()) => { +describe("Box", () => { + test("should render with columns correctly", () => { expect( Renderer.create( @@ -13,7 +14,7 @@ describe("Box", (. ()) => { )->toMatchSnapshot }) - it("should render without columns correctly", (. ()) => { + test("should render without columns correctly", () => { expect( Renderer.create( diff --git a/core/src/components/grid/Ancestor_Grid_Test.res b/core/src/components/grid/Ancestor_Grid_Test.res index ce375f01..893b061d 100644 --- a/core/src/components/grid/Ancestor_Grid_Test.res +++ b/core/src/components/grid/Ancestor_Grid_Test.res @@ -1,10 +1,11 @@ -open Ancestor_Jest +open Jest +open Expect open Ancestor module Renderer = Ancestor_ReactTestRenderer -describe("Grid", (. ()) => { - it("should with spacing render correctly", (. ()) => { +describe("Grid", () => { + test("should with spacing render correctly", () => { expect( Renderer.create( @@ -17,7 +18,7 @@ describe("Grid", (. ()) => { )->toMatchSnapshot }) - it("should without spacing render correctly", (. ()) => { + test("should without spacing render correctly", () => { expect( Renderer.create( diff --git a/core/src/components/hidden/Ancestor_Hidden_Test.res b/core/src/components/hidden/Ancestor_Hidden_Test.res index 5c33bcfe..ebcc4386 100644 --- a/core/src/components/hidden/Ancestor_Hidden_Test.res +++ b/core/src/components/hidden/Ancestor_Hidden_Test.res @@ -1,10 +1,11 @@ -open Ancestor_Jest +open Jest +open Expect open Ancestor module Renderer = Ancestor_ReactTestRenderer -describe("Hidden", (. ()) => { - it("should visually hide elements correctly", (. ()) => { +describe("Hidden", () => { + test("should visually hide elements correctly", () => { expect( Renderer.create( diff --git a/core/src/components/stack/Ancestor_Stack_Test.res b/core/src/components/stack/Ancestor_Stack_Test.res index f4407709..477b77ce 100644 --- a/core/src/components/stack/Ancestor_Stack_Test.res +++ b/core/src/components/stack/Ancestor_Stack_Test.res @@ -1,9 +1,10 @@ -open Ancestor_Jest +open Jest +open Expect open Ancestor module Renderer = Ancestor_ReactTestRenderer -describe("Stack", (. ()) => { - it("should render correctly", (. ()) => { +describe("Stack", () => { + test("should render correctly", () => { expect( Renderer.create( @@ -13,7 +14,7 @@ describe("Stack", (. ()) => { )->toMatchSnapshot }) - it("should render with dividers correctly", (. ()) => { + test("should render with dividers correctly", () => { let placeholder =
{`Placeholder`->React.string}
let divider =
{`Divider`->React.string}
diff --git a/core/src/core/Ancestor_Styles_Test.res b/core/src/core/Ancestor_Styles_Test.res index a567b7c2..bd56f951 100644 --- a/core/src/core/Ancestor_Styles_Test.res +++ b/core/src/core/Ancestor_Styles_Test.res @@ -1,12 +1,13 @@ -open Ancestor_Jest +open Jest +open Expect module Styles = Ancestor_Styles.Make(Ancestor.DefaultConfig) -describe("Styles", (. ()) => { - describe(".createCssValueFromArray", (. ()) => { - it( +describe("Styles", () => { + describe(".createCssValueFromArray", () => { + test( "should create responsive CSS for the attribute provided", - (. ()) => { + () => { let padding = Styles.createCssValueFromArray( "padding", Some({xs: 2, md: 4}), @@ -25,10 +26,10 @@ describe("Styles", (. ()) => { ) }) - describe(".mediaQuery", (. ()) => { - it( + describe(".mediaQuery", () => { + test( "should create a media query correctly", - (. ()) => { + () => { let mediaQuery = Styles.mediaQuery("display: block;", Xs, "display: flex") expect(mediaQuery)->toMatchSnapshot @@ -36,10 +37,10 @@ describe("Styles", (. ()) => { ) }) - describe(".createResponsiveProp", (. ()) => { - it( + describe(".createResponsiveProp", () => { + test( "should create responsive styles correctly", - (. ()) => { + () => { let styles = Styles.createResponsiveProp( ~prop=Some({xs: 1, md: 2}), value => `padding: ${value->Js.Int.toString};`, @@ -49,9 +50,9 @@ describe("Styles", (. ()) => { }, ) - it( + test( "should add default styles correctly", - (. ()) => { + () => { let styles = Styles.createResponsiveProp( ~prop=None, ~defaultStyles="border: solid 1px red;", diff --git a/core/src/core/css/Ancestor_Css_Test.res b/core/src/core/css/Ancestor_Css_Test.res index 9c127f88..f0ea36cb 100644 --- a/core/src/core/css/Ancestor_Css_Test.res +++ b/core/src/core/css/Ancestor_Css_Test.res @@ -1,4 +1,5 @@ -open Ancestor_Jest +open Jest +open Expect include Ancestor_Css.Make({ type spacing = int @@ -8,130 +9,154 @@ include Ancestor_Css.Make({ let colors = v => v }) -describe("Ancestor_Css", (. ()) => { - describe("Length.toString", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(Length) - expect(toString(#rem(10.2)))->toBe(`10.2rem`) - expect(toString(#em(7.5)))->toBe(`7.5em`) - expect(toString(#px(1)))->toBe(`1px`) - expect(toString(#pct(100.0)))->toBe(`100%`) - - expect(#add(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem + 10px)`) - expect(#sub(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem - 10px)`) - expect(#div(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem / 10px)`) - expect(#mult(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem * 10px)`) - }) +describe("Ancestor_Css", () => { + describe("Length.toString", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(Length) + expect(toString(#rem(10.2)))->toBe(`10.2rem`) + expect(toString(#em(7.5)))->toBe(`7.5em`) + expect(toString(#px(1)))->toBe(`1px`) + expect(toString(#pct(100.0)))->toBe(`100%`) + + expect(#add(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem + 10px)`) + expect(#sub(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem - 10px)`) + expect(#div(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem / 10px)`) + expect(#mult(1.6->#rem, 10->#px)->toString)->toBe(`calc(1.6rem * 10px)`) + }, + ) }) - describe("Transform.toString", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(Transform) - expect(toString(#translate(10.0->#rem, 20.0->#rem)))->toBe(`translate(10rem, 20rem)`) - - expect( - toString(#translate3d(10->#px, 15->#px, 20->#px)), - )->toBe(`translate3d(10px, 15px, 20px)`) - - expect(#translateX(10->#px)->toString)->toBe(`translateX(10px)`) - expect(#translateY(15->#px)->toString)->toBe(`translateY(15px)`) - expect(#translateZ(20->#px)->toString)->toBe(`translateZ(20px)`) - - expect(#scale(1.0, 0.5)->toString)->toBe(`scale(1, 0.5)`) - expect(#scaleY(1.5)->toString)->toBe(`scaleY(1.5)`) - expect(#scaleY(0.5)->toString)->toBe(`scaleY(0.5)`) - expect(#scaleX(1.5)->toString)->toBe(`scaleX(1.5)`) - expect(#scaleX(0.8)->toString)->toBe(`scaleX(0.8)`) - - expect(#rotate(125.0->#deg)->toString)->toBe(`rotate(125deg)`) - expect( - #rotate3d(125.5, 135.5, 145.5, 155.5->#deg)->toString, - )->toBe(`rotate3d(125.5, 135.5, 145.5, 155.5deg)`) - - expect(#rotateX(125.0->#deg)->toString)->toBe(`rotateX(125deg)`) - expect(#rotateY(125.0->#deg)->toString)->toBe(`rotateY(125deg)`) - expect(#rotateZ(125.0->#deg)->toString)->toBe(`rotateZ(125deg)`) - - expect(#skew(125.0->#deg, 225.0->#deg)->toString)->toBe(`skew(125deg, 225deg)`) - expect(#skewY(125.0->#deg)->toString)->toBe(`skewY(125deg)`) - expect(#skewX(125.0->#deg)->toString)->toBe(`skewX(125deg)`) - expect(#perspective(125)->toString)->toBe(`perspective(125)`) - }) + describe("Transform.toString", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(Transform) + expect(toString(#translate(10.0->#rem, 20.0->#rem)))->toBe(`translate(10rem, 20rem)`) + + expect( + toString(#translate3d(10->#px, 15->#px, 20->#px)), + )->toBe(`translate3d(10px, 15px, 20px)`) + + expect(#translateX(10->#px)->toString)->toBe(`translateX(10px)`) + expect(#translateY(15->#px)->toString)->toBe(`translateY(15px)`) + expect(#translateZ(20->#px)->toString)->toBe(`translateZ(20px)`) + + expect(#scale(1.0, 0.5)->toString)->toBe(`scale(1, 0.5)`) + expect(#scaleY(1.5)->toString)->toBe(`scaleY(1.5)`) + expect(#scaleY(0.5)->toString)->toBe(`scaleY(0.5)`) + expect(#scaleX(1.5)->toString)->toBe(`scaleX(1.5)`) + expect(#scaleX(0.8)->toString)->toBe(`scaleX(0.8)`) + + expect(#rotate(125.0->#deg)->toString)->toBe(`rotate(125deg)`) + expect( + #rotate3d(125.5, 135.5, 145.5, 155.5->#deg)->toString, + )->toBe(`rotate3d(125.5, 135.5, 145.5, 155.5deg)`) + + expect(#rotateX(125.0->#deg)->toString)->toBe(`rotateX(125deg)`) + expect(#rotateY(125.0->#deg)->toString)->toBe(`rotateY(125deg)`) + expect(#rotateZ(125.0->#deg)->toString)->toBe(`rotateZ(125deg)`) + + expect(#skew(125.0->#deg, 225.0->#deg)->toString)->toBe(`skew(125deg, 225deg)`) + expect(#skewY(125.0->#deg)->toString)->toBe(`skewY(125deg)`) + expect(#skewX(125.0->#deg)->toString)->toBe(`skewX(125deg)`) + expect(#perspective(125)->toString)->toBe(`perspective(125)`) + }, + ) }) - describe("Gap.toString", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(Gap) - - expect(#one(1)->toString)->toBe(`8px`) - expect(#two(1, 2)->toString)->toBe(`8px 16px`) - - expect(#inherit->toString)->toBe(`inherit`) - expect(#unset->toString)->toBe(`unset`) - expect(#revert->toString)->toBe(`revert`) - expect(#initial->toString)->toBe(`initial`) - }) + describe("Gap.toString", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(Gap) + + expect(#one(1)->toString)->toBe(`8px`) + expect(#two(1, 2)->toString)->toBe(`8px 16px`) + + expect(#inherit->toString)->toBe(`inherit`) + expect(#unset->toString)->toBe(`unset`) + expect(#revert->toString)->toBe(`revert`) + expect(#initial->toString)->toBe(`initial`) + }, + ) }) - describe("ListStyle", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(ListStyle) + describe("ListStyle", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(ListStyle) - expect(#short(#square, #inside, #none)->toString)->toBe(`square inside none`) + expect(#short(#square, #inside, #none)->toString)->toBe(`square inside none`) - expect(#inherit->toString)->toBe(`inherit`) - expect(#unset->toString)->toBe(`unset`) - expect(#revert->toString)->toBe(`revert`) - expect(#initial->toString)->toBe(`initial`) - }) + expect(#inherit->toString)->toBe(`inherit`) + expect(#unset->toString)->toBe(`unset`) + expect(#revert->toString)->toBe(`revert`) + expect(#initial->toString)->toBe(`initial`) + }, + ) }) - describe("BackgroundSize", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(BackgroundSize) - - expect(#cover->toString)->toBe(`cover`) - expect(#contain->toString)->toBe(`contain`) - expect(#inherit->toString)->toBe(`inherit`) - expect(#initial->toString)->toBe(`initial`) - expect(#unset->toString)->toBe(`unset`) - expect(#auto->toString)->toBe(`auto`) - expect(#length(12.5->#rem)->toString)->toBe(`12.5rem`) - }) + describe("BackgroundSize", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(BackgroundSize) + + expect(#cover->toString)->toBe(`cover`) + expect(#contain->toString)->toBe(`contain`) + expect(#inherit->toString)->toBe(`inherit`) + expect(#initial->toString)->toBe(`initial`) + expect(#unset->toString)->toBe(`unset`) + expect(#auto->toString)->toBe(`auto`) + expect(#length(12.5->#rem)->toString)->toBe(`12.5rem`) + }, + ) }) - describe("BackgroundPosition.toString", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(BackgroundPosition) - - expect(#top->toString)->toBe(`top`) - expect(#bottom->toString)->toBe(`bottom`) - expect(#left->toString)->toBe(`left`) - expect(#right->toString)->toBe(`right`) - expect(#center->toString)->toBe(`center`) - expect(#inherit->toString)->toBe(`inherit`) - expect(#initial->toString)->toBe(`initial`) - expect(#unset->toString)->toBe(`unset`) - expect(#length(3.5->#rem)->toString)->toBe(`3.5rem`) - }) + describe("BackgroundPosition.toString", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(BackgroundPosition) + + expect(#top->toString)->toBe(`top`) + expect(#bottom->toString)->toBe(`bottom`) + expect(#left->toString)->toBe(`left`) + expect(#right->toString)->toBe(`right`) + expect(#center->toString)->toBe(`center`) + expect(#inherit->toString)->toBe(`inherit`) + expect(#initial->toString)->toBe(`initial`) + expect(#unset->toString)->toBe(`unset`) + expect(#length(3.5->#rem)->toString)->toBe(`3.5rem`) + }, + ) }) - describe("BackgroundImage.toString", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(BackgroundImage) + describe("BackgroundImage.toString", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(BackgroundImage) - expect(#url("path/to/image.png")->toString)->toBe(`url("path/to/image.png")`) - expect(#none->toString)->toBe(`none`) - }) + expect(#url("path/to/image.png")->toString)->toBe(`url("path/to/image.png")`) + expect(#none->toString)->toBe(`none`) + }, + ) }) - describe("FontFamily.toString", (. ()) => { - it("should convert into string correctly", (. ()) => { - let {toString} = module(FontFamily) - - expect(#custom(["DM Sans", "sans-serif"])->toString)->toBe(`DM Sans, sans-serif`) - expect(#initial->toString)->toBe(`initial`) - expect(#inherit->toString)->toBe(`inherit`) - }) + describe("FontFamily.toString", () => { + test( + "should convert into string correctly", + () => { + let {toString} = module(FontFamily) + + expect(#custom(["DM Sans", "sans-serif"])->toString)->toBe(`DM Sans, sans-serif`) + expect(#initial->toString)->toBe(`initial`) + expect(#inherit->toString)->toBe(`inherit`) + }, + ) }) }) diff --git a/core/src/hooks/Ancestor_ResponsiveValueHook_Test.res b/core/src/hooks/Ancestor_ResponsiveValueHook_Test.res index d1eb47d9..31926025 100644 --- a/core/src/hooks/Ancestor_ResponsiveValueHook_Test.res +++ b/core/src/hooks/Ancestor_ResponsiveValueHook_Test.res @@ -1,4 +1,5 @@ -open Ancestor_Jest +open Jest +open Expect open Ancestor_TestingLibrary /** @@ -16,11 +17,11 @@ open Ancestor_TestingLibrary @val external window: Dom.window = "window" @send external resizeTo: (Dom.window, int) => unit = "resizeTo" -describe("ResponsiveValueHook", (. ()) => { - describe(".useResponsiveValue(...)", (. ()) => { - it( +describe("ResponsiveValueHook", () => { + describe(".useResponsiveValue(...)", () => { + test( "should returns the responsive value correctly", - (. ()) => { + () => { let {result} = renderHook( () => Ancestor.useResponsiveValue("Default", {xs: "Mobile", md: "Tablet"}), ) diff --git a/yarn.lock b/yarn.lock index 3a493d52..ba51ce5b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4431,11 +4431,16 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@greenlabs/ppx-ts@^0.1.6": +"@greenlabs/ppx-ts@0.1.6": version "0.1.6" resolved "https://registry.yarnpkg.com/@greenlabs/ppx-ts/-/ppx-ts-0.1.6.tgz#9f27e1b829d73b584023fbe17034aef9f25e6e67" integrity sha512-L5pX5XO2tipVyoyj7Sp0frgPqW/v4YUQ3jP24dd4885F5FWG33diGkaYPns/hqwCkcPgI+wvgvixL6y0PXTaWw== +"@greenlabs/rescript-jest@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@greenlabs/rescript-jest/-/rescript-jest-1.0.1.tgz#66942a19c17aac7e0d66d3fd516859ca618c37d9" + integrity sha512-gapjcZ3DFQ/7Inrhz6QcoyPVL8eEdqUwLLmdwlKcMI/j6JPyZGe7VI6cldEGQ9/Emgpjmf68DT3PjVype68Cdw== + "@hapi/hoek@^9.0.0": version "9.2.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131" @@ -6079,7 +6084,7 @@ lz-string "^1.4.4" pretty-format "^27.0.2" -"@testing-library/react-hooks@^8.0.1": +"@testing-library/react-hooks@8.0.1": version "8.0.1" resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12" integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==