From 96fbd29fb8b30473813db9057b3649f7ebadd6e3 Mon Sep 17 00:00:00 2001 From: Winton DeShong Date: Fri, 26 Jun 2020 11:18:21 -0400 Subject: [PATCH 1/5] Added use-localization hook along with necessary i18next deps --- package-lock.json | 66 +++++++++++++++++++++++++++++++---- package.json | 4 ++- src/hooks/use-localization.ts | 18 ++++++++++ src/index.ts | 31 ++++++++++------ 4 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 src/hooks/use-localization.ts diff --git a/package-lock.json b/package-lock.json index 72c749b..d74202d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1046,13 +1046,15 @@ } }, "andculturecode-javascript-core": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/andculturecode-javascript-core/-/andculturecode-javascript-core-0.0.7.tgz", - "integrity": "sha512-AfBiuB2MlInHcCb4BGK/WKew0gYmo/hhXbdKoN9DFC/OCPDRLh0qBLSFHifgmVfV16T3ryLzXh5f2KIvcdWlhg==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/andculturecode-javascript-core/-/andculturecode-javascript-core-0.1.0.tgz", + "integrity": "sha512-/wGg8Z+m3CA9y9kRUkGYOTxXWXgsb18UardXkvi7UEClYj1BgdiMh6PuIWXGoE/agU8m8qBEXBJxExaSX4awPg==", "requires": { "axios": "0.19.2", + "i18next": "19.4.5", "immutable": "4.0.0-rc.12", - "lodash": "4.17.15" + "lodash": "4.17.15", + "query-string": "6.13.1" } }, "andculturecode-javascript-testing": { @@ -1740,8 +1742,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "deep-is": { "version": "0.1.3", @@ -2408,6 +2409,15 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "html-parse-stringify2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz", + "integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=", + "dev": true, + "requires": { + "void-elements": "^2.0.1" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -2425,6 +2435,14 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "i18next": { + "version": "19.4.5", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.4.5.tgz", + "integrity": "sha512-aLvSsURoupi3x9IndmV6+m3IGhzLzhYv7Gw+//K3ovdliyGcFRV0I1MuddI0Bk/zR7BG1U+kJOjeHFUcUIdEgg==", + "requires": { + "@babel/runtime": "^7.3.1" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4375,6 +4393,16 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "query-string": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.1.tgz", + "integrity": "sha512-RfoButmcK+yCta1+FuU8REvisx1oEzhMKwhLUNcepQTPGcNMp1sIqjnfCtfnvGSQZQEhaBHvccujtWoUV3TTbA==", + "requires": { + "decode-uri-component": "^0.2.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, "react": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", @@ -4396,6 +4424,16 @@ "scheduler": "^0.19.1" } }, + "react-i18next": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.6.0.tgz", + "integrity": "sha512-koyvoDgmY7y7vlbUOVWyoHahbBABfBse9X1vgYFw/WI+CfZwjumZ2/zQGYqLoMx6lEa0c9Lxr9GNP9L3HAJYUg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.3.1", + "html-parse-stringify2": "2.0.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -5122,6 +5160,11 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -5187,6 +5230,11 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + }, "string-length": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", @@ -5748,6 +5796,12 @@ "extsprintf": "^1.2.0" } }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index 6f84051..832d5a4 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "url": "https://github.com/AndcultureCode/AndcultureCode.JavaScript.React/issues" }, "dependencies": { - "andculturecode-javascript-core": "0.0.7", + "andculturecode-javascript-core": "0.1.0", "axios": "0.19.2", "immutable": "4.0.0-rc.12", "react": "16.13.1", @@ -26,10 +26,12 @@ "@types/react-router-dom": "5.1.5", "@types/rosie": "0.0.37", "andculturecode-javascript-testing": "0.0.2", + "i18next": "19.4.5", "jest": "25.5.4", "jest-extended": "0.11.5", "jest-fetch-mock": "3.0.3", "prettier": "1.19.1", + "react-i18next": "11.6.0", "rimraf": "2.6.2", "rosie": "2.0.1", "ts-jest": "25.5.1", diff --git a/src/hooks/use-localization.ts b/src/hooks/use-localization.ts new file mode 100644 index 0000000..0d24288 --- /dev/null +++ b/src/hooks/use-localization.ts @@ -0,0 +1,18 @@ +import { useCallback } from "react"; +import { useTranslation } from "react-i18next"; + +/** + * Typed wrapper of i18n `useTranslation` hook + */ +const useLocalization = () => { + const { t } = useTranslation(); + + const translate = (key: K, options?: object) => + t(key as string, options); + + return { + t: useCallback(translate, [t]), + }; +}; + +export { useLocalization }; diff --git a/src/index.ts b/src/index.ts index a91797f..b22f32c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,16 @@ export { } from "./components/routing/nested-routes-by-property"; export { Redirects, RedirectsProps } from "./components/routing/redirects"; -//#endregion Components +// #endregion Components + +// ----------------------------------------------------------------------------------------- +// #region Hooks +// ----------------------------------------------------------------------------------------- + +export { useCancellablePromise } from "./hooks/use-cancellable-promise"; +export { useLocalization } from "./hooks/use-localization"; + +// #endregion // ----------------------------------------------------------------------------------------- // #region Interfaces @@ -30,7 +39,7 @@ export { RedirectDefinition } from "./interfaces/redirect-definition"; export { RouteDefinition } from "./interfaces/route-definition"; export { RouteMap } from "./interfaces/route-map"; -//#endregion Interfaces +// #endregion Interfaces // ----------------------------------------------------------------------------------------- // #region Services @@ -38,7 +47,7 @@ export { RouteMap } from "./interfaces/route-map"; export { ServiceFactory } from "./services/service-factory"; -//#endregion Services +// #endregion Services // ----------------------------------------------------------------------------------------- // #region Utilities @@ -46,7 +55,7 @@ export { ServiceFactory } from "./services/service-factory"; export { RouteUtils } from "./utilities/route-utils"; -//#endregion Utilities +// #endregion Utilities // ----------------------------------------------------------------------------------------- // #region Vendor @@ -56,8 +65,10 @@ export { RouteUtils } from "./utilities/route-utils"; // specific component or function for their own implemention alongside our library. export { generatePath, - Prompt, + match, + matchPath, MemoryRouter, + Prompt, RedirectProps, Redirect, RouteChildrenProps, @@ -65,17 +76,15 @@ export { RouteProps, Route, Router, + RouterChildContext, StaticRouter, - SwitchProps, Switch, - match, - matchPath, - withRouter, - RouterChildContext, + SwitchProps, useHistory, useLocation, useParams, useRouteMatch, + withRouter, } from "react-router-dom"; -//#endregion Vendor +// #endregion Vendor From 2c6fe7910fb798fb3ad45783821c408bde9c2aa1 Mon Sep 17 00:00:00 2001 From: Winton DeShong Date: Fri, 26 Jun 2020 11:23:23 -0400 Subject: [PATCH 2/5] Stub in useLocalization test file --- src/hooks/use-localization.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/hooks/use-localization.test.ts diff --git a/src/hooks/use-localization.test.ts b/src/hooks/use-localization.test.ts new file mode 100644 index 0000000..c596126 --- /dev/null +++ b/src/hooks/use-localization.test.ts @@ -0,0 +1,7 @@ +import { Factory } from "rosie"; +import { FactoryType } from "../tests/factories/factory-type"; +import "jest-extended"; + +describe("useLocalization", () => { + test.skip("TODO", () => {}); +}); From fbdd02a1bb30b9fd147fa63fcdf9bfe3c1783a67 Mon Sep 17 00:00:00 2001 From: Winton DeShong Date: Fri, 26 Jun 2020 14:45:51 -0400 Subject: [PATCH 3/5] Unit testing use-localization hook --- package-lock.json | 12 +++++ package.json | 3 ++ src/hooks/use-localization.test.ts | 7 --- src/hooks/use-localization.test.tsx | 80 +++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 7 deletions(-) delete mode 100644 src/hooks/use-localization.test.ts create mode 100644 src/hooks/use-localization.test.tsx diff --git a/package-lock.json b/package-lock.json index d74202d..9d2129d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -801,6 +801,12 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/faker": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/faker/-/faker-4.1.12.tgz", + "integrity": "sha512-0MEyzJrLLs1WaOCx9ULK6FzdCSj2EuxdSP9kvuxxdBEGujZYUOZ4vkPXdgu3dhyg/pOdn7VCatelYX7k0YShlA==", + "dev": true + }, "@types/graceful-fs": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", @@ -2090,6 +2096,12 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, + "faker": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", + "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=", + "dev": true + }, "fast-deep-equal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", diff --git a/package.json b/package.json index 832d5a4..a3908aa 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "devDependencies": { "@testing-library/jest-dom": "5.5.0", "@testing-library/react": "10.0.4", + "@types/faker": "^4.1.12", "@types/jest": "25.1.5", "@types/node": "13.11.0", "@types/react": "16.9.26", @@ -26,6 +27,7 @@ "@types/react-router-dom": "5.1.5", "@types/rosie": "0.0.37", "andculturecode-javascript-testing": "0.0.2", + "faker": "4.1.0", "i18next": "19.4.5", "jest": "25.5.4", "jest-extended": "0.11.5", @@ -71,6 +73,7 @@ "prepublishOnly": "npm run build", "test": "jest ./src", "watch": "npm run build -- --watch", + "watch:coverage": "jest ./src --coverage --watch", "watch:test": "jest ./src --watch" }, "types": "dist/index", diff --git a/src/hooks/use-localization.test.ts b/src/hooks/use-localization.test.ts deleted file mode 100644 index c596126..0000000 --- a/src/hooks/use-localization.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Factory } from "rosie"; -import { FactoryType } from "../tests/factories/factory-type"; -import "jest-extended"; - -describe("useLocalization", () => { - test.skip("TODO", () => {}); -}); diff --git a/src/hooks/use-localization.test.tsx b/src/hooks/use-localization.test.tsx new file mode 100644 index 0000000..986a7bd --- /dev/null +++ b/src/hooks/use-localization.test.tsx @@ -0,0 +1,80 @@ +import React, { useEffect } from "react"; +import "jest-extended"; +import faker from "faker"; +import { + BaseEnglishUnitedStates, + Culture, + LocalizationUtils, +} from "andculturecode-javascript-core"; +import { useLocalization } from "./use-localization"; +import { render, wait, waitFor } from "@testing-library/react"; +import { initReactI18next } from "react-i18next"; + +describe("useLocalization", () => { + test("given translations are configured, when invalid key, returns key", async () => { + // Arrange + const expectedKey = faker.random.word(); + const culture: Partial> = { resources: {} }; + const EnglishUnitedStates = LocalizationUtils.cultureFactory( + BaseEnglishUnitedStates, + culture + ); + + const TestComponent = () => { + const { t } = useLocalization(); + + return

{t(expectedKey)}

; + }; + + const TestApp = () => { + LocalizationUtils.initialize(initReactI18next, [ + EnglishUnitedStates, + ]); + + return ; + }; + + // Act + const { getByText } = render(); + + // Assert + await waitFor(() => { + expect(getByText(expectedKey)).toBeInTheDocument(); + }); + }); + + test("given translations are configured, when valid key, returns translation", async () => { + // Arrange + const key = "testkey"; + const expectedValue = faker.random.words(); + const culture: Partial> = { resources: {} }; + culture.resources[key] = expectedValue; + + const EnglishUnitedStates = LocalizationUtils.cultureFactory( + BaseEnglishUnitedStates, + culture + ); + + const TestComponent = () => { + const { t } = useLocalization(); + + return

{t(key)}

; + }; + + const TestApp = () => { + LocalizationUtils.initialize(initReactI18next, [ + EnglishUnitedStates, + ]); + + return ; + }; + + // Act + const { getByText } = render(); + + // Assert + await waitFor(() => { + expect(getByText(expectedValue)).toBeInTheDocument(); + }); + }); +}); From d0b65ff1ccf7416f6734ee5425982d2d36dd84f8 Mon Sep 17 00:00:00 2001 From: Winton DeShong Date: Fri, 26 Jun 2020 14:49:56 -0400 Subject: [PATCH 4/5] Quick refactor of redundant wording in use-localization tests --- src/hooks/use-localization.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/use-localization.test.tsx b/src/hooks/use-localization.test.tsx index 986a7bd..19e4675 100644 --- a/src/hooks/use-localization.test.tsx +++ b/src/hooks/use-localization.test.tsx @@ -11,7 +11,7 @@ import { render, wait, waitFor } from "@testing-library/react"; import { initReactI18next } from "react-i18next"; describe("useLocalization", () => { - test("given translations are configured, when invalid key, returns key", async () => { + test("when invalid key, returns key", async () => { // Arrange const expectedKey = faker.random.word(); const culture: Partial> = { resources: {} }; @@ -43,7 +43,7 @@ describe("useLocalization", () => { }); }); - test("given translations are configured, when valid key, returns translation", async () => { + test("when valid key, returns translation", async () => { // Arrange const key = "testkey"; const expectedValue = faker.random.words(); From 20cbb196d999cc6597ea4660c94c4eefe09eecd3 Mon Sep 17 00:00:00 2001 From: Winton DeShong Date: Fri, 26 Jun 2020 14:55:29 -0400 Subject: [PATCH 5/5] Update deps to be exact versions --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a3908aa..82668c0 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "devDependencies": { "@testing-library/jest-dom": "5.5.0", "@testing-library/react": "10.0.4", - "@types/faker": "^4.1.12", + "@types/faker": "4.1.12", "@types/jest": "25.1.5", "@types/node": "13.11.0", "@types/react": "16.9.26", @@ -39,8 +39,8 @@ "ts-jest": "25.5.1", "tslint": "6.1.2", "tslint-config-prettier": "1.18.0", - "typedoc": "^0.17.6", - "typedoc-plugin-markdown": "^2.2.17", + "typedoc": "0.17.6", + "typedoc-plugin-markdown": "2.2.17", "typescript": "3.8.3" }, "files": [