From 18f917db2138cbda31ced1311426e639d6bba9ad Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Wed, 26 May 2021 17:19:00 -0400 Subject: [PATCH 01/14] add network information context, provider, and hook --- package-lock.json | 32 ++------------- package.json | 7 +++- src/hooks/use-network-connection.ts | 6 +++ .../network-connection-context.ts | 6 +++ .../network-connection-provider.tsx | 41 +++++++++++++++++++ 5 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 src/hooks/use-network-connection.ts create mode 100644 src/providers/network-connection/network-connection-context.ts create mode 100644 src/providers/network-connection/network-connection-provider.tsx diff --git a/package-lock.json b/package-lock.json index 7f510e3..4e57f92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -894,12 +894,6 @@ } } }, - "@types/lodash": { - "version": "4.14.108", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.108.tgz", - "integrity": "sha512-WD2vUOKfBBVHxWUV9iMR9RMfpuf8HquxWeAq2yqGVL7Nc4JW2+sQama0pREMqzNI3Tutj0PyxYUJwuoxxvX+xA==", - "dev": true - }, "@types/node": { "version": "13.11.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz", @@ -1087,26 +1081,12 @@ } }, "andculturecode-javascript-core": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/andculturecode-javascript-core/-/andculturecode-javascript-core-0.4.3.tgz", - "integrity": "sha512-ESgYm/1uSAPf03erLJyLIQ6t5dnGl47yD0Fb9NMO8g7BPPeM/iO7vV7maxtSlSO9wuJbPstWcg+nKW374/O9bQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/andculturecode-javascript-core/-/andculturecode-javascript-core-0.6.0.tgz", + "integrity": "sha512-nMol8JZ5cNYUQ1ZYtqaGInbhxTW6bQUHJKMCLUK69OuoCfhX/N0PwUFPsamIAQVLpn7K0+Fgf13/DwZLTExP1w==", "dev": true, "requires": { - "@types/lodash": "4.14.108", - "axios": "0.19.2", - "humanize-plus": "1.8.2", - "i18next": "19.4.5", - "immutable": "4.0.0-rc.12", - "lodash": "4.17.19", "query-string": "6.13.1" - }, - "dependencies": { - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true - } } }, "andculturecode-javascript-testing": { @@ -2554,12 +2534,6 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "humanize-plus": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz", - "integrity": "sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA=", - "dev": true - }, "i18next": { "version": "19.4.5", "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.4.5.tgz", diff --git a/package.json b/package.json index 90c469f..0ca3ffe 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@types/react-dom": "16.9.6", "@types/react-router-dom": "5.1.5", "@types/rosie": "0.0.37", - "andculturecode-javascript-core": "0.4.3", + "andculturecode-javascript-core": "0.6.0", "andculturecode-javascript-testing": "0.0.2", "axios": "0.19.2", "cross-env": "6.0.3", @@ -62,10 +62,13 @@ "main": "dist/index", "name": "andculturecode-javascript-react", "peerDependencies": { - "andculturecode-javascript-core": "^0.4.3", + "andculturecode-javascript-core": "^0.6.0", "axios": "^0.19.2", + "humanize-plus": "^1.8.2", "i18next": "^19.4.5", + "i18next-browser-languagedetector": "^6.0.1", "immutable": "^4.0.0-rc.12", + "lodash": "^4.17.19", "react": "^16.13.1", "react-dom": "^16.13.1", "react-i18next": "^11.6.0", diff --git a/src/hooks/use-network-connection.ts b/src/hooks/use-network-connection.ts new file mode 100644 index 0000000..b1a2230 --- /dev/null +++ b/src/hooks/use-network-connection.ts @@ -0,0 +1,6 @@ +import { useContext } from "react"; +import { NetworkConnectionContext } from "../providers/network-connection/network-connection-context"; + +export default function useNetworkConnection() { + return useContext(NetworkConnectionContext); +} diff --git a/src/providers/network-connection/network-connection-context.ts b/src/providers/network-connection/network-connection-context.ts new file mode 100644 index 0000000..56afa82 --- /dev/null +++ b/src/providers/network-connection/network-connection-context.ts @@ -0,0 +1,6 @@ +import { NetworkConnection } from "andculturecode-javascript-core"; +import React from "react"; + +export const NetworkConnectionContext = React.createContext({ + isOnline: true, +}); diff --git a/src/providers/network-connection/network-connection-provider.tsx b/src/providers/network-connection/network-connection-provider.tsx new file mode 100644 index 0000000..8707c6c --- /dev/null +++ b/src/providers/network-connection/network-connection-provider.tsx @@ -0,0 +1,41 @@ +import { + NetworkConnection, + NetworkInformationUtils, +} from "andculturecode-javascript-core"; +import React, { useCallback, useEffect, useState } from "react"; +import { NetworkConnectionContext } from "./network-connection-context"; + +const NetworkInformationProvider: React.FC = ({ children }) => { + const [state, setState] = useState( + NetworkInformationUtils.getNetworkConnection() + ); + + const loadNetworkInformation = useCallback(() => { + const networkConnection = NetworkInformationUtils.getNetworkConnection(); + + setState((prev) => ({ + ...prev, + ...networkConnection, + })); + }, []); + + useEffect(() => { + const { connection } = window.navigator as any; + + connection?.addEventListener("change", loadNetworkInformation); + + loadNetworkInformation(); + + return () => { + connection?.removeEventListener("change", loadNetworkInformation); + }; + }, [loadNetworkInformation]); + + return ( + + {children} + + ); +}; + +export default NetworkInformationProvider; From 7a66e0c10f00a264094fc498fc74451d8613d648 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Fri, 28 May 2021 08:33:17 -0400 Subject: [PATCH 02/14] add devDependencies --- package-lock.json | 27 ++++++++++++++++++++++++--- package.json | 3 +++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4e57f92..6fd1d56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1112,6 +1112,12 @@ "requires": { "follow-redirects": "1.5.10" } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true } } }, @@ -2534,6 +2540,12 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "humanize-plus": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz", + "integrity": "sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA=", + "dev": true + }, "i18next": { "version": "19.4.5", "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.4.5.tgz", @@ -2543,6 +2555,15 @@ "@babel/runtime": "^7.3.1" } }, + "i18next-browser-languagedetector": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.1.tgz", + "integrity": "sha512-hckgbBdCpJPhkGUANe6tsvD52k9R7GuYskG0EaIw89pZz3owUvUEwXHqM5pX1Pn93jz+O65Y09ikwJrMkqtq2Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.5" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3877,9 +3898,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.memoize": { diff --git a/package.json b/package.json index 0ca3ffe..67563a0 100644 --- a/package.json +++ b/package.json @@ -25,11 +25,14 @@ "axios": "0.19.2", "cross-env": "6.0.3", "faker": "4.1.0", + "humanize-plus": "^1.8.2", + "i18next-browser-languagedetector": "^6.0.1", "i18next": "19.4.5", "immutable": "4.0.0-rc.12", "jest": "25.5.4", "jest-extended": "0.11.5", "jest-fetch-mock": "3.0.3", + "lodash": "^4.17.19", "prettier": "1.19.1", "react": "16.13.1", "react-dom": "16.13.1", From 9ab69e7dbf7f673009e77429487b7d6f07830aac Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Tue, 22 Jun 2021 06:48:25 -0400 Subject: [PATCH 03/14] update network-connection-provider and add tests --- .../network-connection-provider.test.tsx | 61 +++++++++++++++++++ .../network-connection-provider.tsx | 13 ++-- 2 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 src/providers/network-connection/network-connection-provider.test.tsx diff --git a/src/providers/network-connection/network-connection-provider.test.tsx b/src/providers/network-connection/network-connection-provider.test.tsx new file mode 100644 index 0000000..6e3a301 --- /dev/null +++ b/src/providers/network-connection/network-connection-provider.test.tsx @@ -0,0 +1,61 @@ +import React from "react"; +import { render } from "@testing-library/react"; +import NetworkConnectionProvider from "./network-connection-provider"; +import { + NetworkConnection, + NetworkInformationUtils, +} from "andculturecode-javascript-core"; +import useNetworkConnection from "../../hooks/use-network-connection"; + +interface SetupSutOptions { + connection?: NetworkConnection; +} + +const setupSut = (options?: SetupSutOptions) => { + const { connection } = options ?? {}; + + jest.spyOn( + NetworkInformationUtils, + "getNetworkConnection" + ).mockImplementation(() => connection); + + const networkConnectionResults: NetworkConnection[] = []; + + function TestComponent() { + const connection = useNetworkConnection(); + networkConnectionResults.push(connection); + + return
; + } + + return { + TestComponent, + networkConnectionResults: { + all: networkConnectionResults, + current: + networkConnectionResults[networkConnectionResults.length - 1], + }, + }; +}; + +describe("NetworkConnectionProvider", () => { + it("renders initial network connection state", () => { + // Arrange + const connection: NetworkConnection = { + isOnline: true, + }; + const { networkConnectionResults, TestComponent } = setupSut({ + connection, + }); + + // Act + render( + + + + ); + + // Assert + expect(networkConnectionResults.current).toEqual(connection); + }); +}); diff --git a/src/providers/network-connection/network-connection-provider.tsx b/src/providers/network-connection/network-connection-provider.tsx index 8707c6c..a703f93 100644 --- a/src/providers/network-connection/network-connection-provider.tsx +++ b/src/providers/network-connection/network-connection-provider.tsx @@ -5,7 +5,7 @@ import { import React, { useCallback, useEffect, useState } from "react"; import { NetworkConnectionContext } from "./network-connection-context"; -const NetworkInformationProvider: React.FC = ({ children }) => { +const NetworkConnectionProvider: React.FC = ({ children }) => { const [state, setState] = useState( NetworkInformationUtils.getNetworkConnection() ); @@ -20,14 +20,17 @@ const NetworkInformationProvider: React.FC = ({ children }) => { }, []); useEffect(() => { - const { connection } = window.navigator as any; + const networkConnection = NetworkInformationUtils.getNetworkConnection(); - connection?.addEventListener("change", loadNetworkInformation); + networkConnection?.addEventListener?.("change", loadNetworkInformation); loadNetworkInformation(); return () => { - connection?.removeEventListener("change", loadNetworkInformation); + networkConnection?.removeEventListener?.( + "change", + loadNetworkInformation + ); }; }, [loadNetworkInformation]); @@ -38,4 +41,4 @@ const NetworkInformationProvider: React.FC = ({ children }) => { ); }; -export default NetworkInformationProvider; +export default NetworkConnectionProvider; From 438bf9b48afd28f7ae42a6ba03486e78db873643 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Tue, 22 Jun 2021 08:13:03 -0400 Subject: [PATCH 04/14] additional network connection provider tests --- .../network-connection-provider.test.tsx | 176 ++++++++++++++++-- 1 file changed, 157 insertions(+), 19 deletions(-) diff --git a/src/providers/network-connection/network-connection-provider.test.tsx b/src/providers/network-connection/network-connection-provider.test.tsx index 6e3a301..380ce40 100644 --- a/src/providers/network-connection/network-connection-provider.test.tsx +++ b/src/providers/network-connection/network-connection-provider.test.tsx @@ -1,43 +1,94 @@ -import React from "react"; -import { render } from "@testing-library/react"; +import React, { useContext } from "react"; +import { act, cleanup, render } from "@testing-library/react"; import NetworkConnectionProvider from "./network-connection-provider"; import { NetworkConnection, NetworkInformationUtils, } from "andculturecode-javascript-core"; -import useNetworkConnection from "../../hooks/use-network-connection"; +import { NetworkConnectionContext } from "./network-connection-context"; + +// ----------------------------------------------------------------------------------------- +// #region Types +// ----------------------------------------------------------------------------------------- + +type TypeFromKey = Type[Key]; + +// #endregion Types + +// ----------------------------------------------------------------------------------------- +// #region Interfaces +// ----------------------------------------------------------------------------------------- interface SetupSutOptions { - connection?: NetworkConnection; + mockConnections?: Array>; +} + +interface SetupSutResults { + TestComponent: () => JSX.Element; + networkConnectionResults: { + all: Array; + current?: NetworkConnection; + }; } -const setupSut = (options?: SetupSutOptions) => { - const { connection } = options ?? {}; +// #endregion Interfaces + +// ----------------------------------------------------------------------------------------- +// #region Mocks +// ----------------------------------------------------------------------------------------- + +const getNetworkConnectionMock = jest.spyOn( + NetworkInformationUtils, + "getNetworkConnection" +); + +// #endregion Mocks + +// ----------------------------------------------------------------------------------------- +// #region Setup +// ----------------------------------------------------------------------------------------- - jest.spyOn( - NetworkInformationUtils, - "getNetworkConnection" - ).mockImplementation(() => connection); +const setupSut = (options?: SetupSutOptions): SetupSutResults => { + const { mockConnections = [] } = options ?? {}; - const networkConnectionResults: NetworkConnection[] = []; + getNetworkConnectionMock.mockReset(); + for (let index = 0; index < mockConnections.length; index++) { + const mockImplementation = + index === mockConnections.length - 1 + ? getNetworkConnectionMock.mockImplementation + : getNetworkConnectionMock.mockImplementationOnce; + + mockImplementation(() => { + return { + isOnline: true, + ...mockConnections[index], + }; + }); + } + + const networkConnectionResults: TypeFromKey< + SetupSutResults, + "networkConnectionResults" + > = { + all: [] as NetworkConnection[], + }; function TestComponent() { - const connection = useNetworkConnection(); - networkConnectionResults.push(connection); + const connection = useContext(NetworkConnectionContext); + networkConnectionResults.all.push(connection); + networkConnectionResults.current = connection; return
; } return { TestComponent, - networkConnectionResults: { - all: networkConnectionResults, - current: - networkConnectionResults[networkConnectionResults.length - 1], - }, + networkConnectionResults, }; }; +// #endregion Setup + describe("NetworkConnectionProvider", () => { it("renders initial network connection state", () => { // Arrange @@ -45,7 +96,7 @@ describe("NetworkConnectionProvider", () => { isOnline: true, }; const { networkConnectionResults, TestComponent } = setupSut({ - connection, + mockConnections: [connection], }); // Act @@ -56,6 +107,93 @@ describe("NetworkConnectionProvider", () => { ); // Assert + expect(networkConnectionResults.all.length).toEqual(2); expect(networkConnectionResults.current).toEqual(connection); }); + + it("adds an event listener", () => { + // Arrange + const addEventListener = jest.fn(); + const { TestComponent } = setupSut({ + mockConnections: [{ addEventListener }], + }); + + // Act + render( + + + + ); + + // Assert + expect(addEventListener).toBeCalled(); + }); + + describe("when change event is called", () => { + it("loads network connection into state", () => { + // Arrange + let loadNetworkInformationCallback = () => {}; + + const mockConnections: Array = [ + { + isOnline: true, + }, + { + isOnline: true, + addEventListener: ( + event: "change", + callback: VoidFunction + ) => { + loadNetworkInformationCallback = callback; + }, + }, + { + isOnline: false, + }, + ]; + + const { networkConnectionResults, TestComponent } = setupSut({ + mockConnections, + }); + + // Act + render( + + + + ); + + act(() => loadNetworkInformationCallback()); + + // Assert + expect(networkConnectionResults.all.length).toEqual( + mockConnections.length + ); + expect(networkConnectionResults.current).toEqual( + mockConnections[2] + ); + }); + }); + + describe("when unmounted", () => { + it("calls removeEventlistener for cleanup", async () => { + // Arrange + const removeEventListener = jest.fn(); + const { TestComponent } = setupSut({ + mockConnections: [{ removeEventListener }], + }); + + // Act + render( + + + + ); + + await cleanup(); + + // Assert + expect(removeEventListener).toBeCalled(); + }); + }); }); From c99cfbce8caa11160d39540cc5aebd101201dc30 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Tue, 22 Jun 2021 14:37:16 -0400 Subject: [PATCH 05/14] address PR comments --- src/contexts/network-connection-context.ts | 6 ++ src/hooks/use-network-connection.test.tsx | 59 +++++++++++++++++++ src/hooks/use-network-connection.ts | 20 +++++-- .../network-connection-provider.test.tsx | 8 +-- .../network-connection-provider.tsx | 22 +++++-- .../network-connection-context.ts | 6 -- 6 files changed, 101 insertions(+), 20 deletions(-) create mode 100644 src/contexts/network-connection-context.ts create mode 100644 src/hooks/use-network-connection.test.tsx rename src/providers/{network-connection => }/network-connection-provider.test.tsx (95%) rename src/providers/{network-connection => }/network-connection-provider.tsx (69%) delete mode 100644 src/providers/network-connection/network-connection-context.ts diff --git a/src/contexts/network-connection-context.ts b/src/contexts/network-connection-context.ts new file mode 100644 index 0000000..79128f0 --- /dev/null +++ b/src/contexts/network-connection-context.ts @@ -0,0 +1,6 @@ +import { NetworkConnection } from "andculturecode-javascript-core"; +import React from "react"; + +export const NetworkConnectionContext = React.createContext< + NetworkConnection | undefined +>(undefined); diff --git a/src/hooks/use-network-connection.test.tsx b/src/hooks/use-network-connection.test.tsx new file mode 100644 index 0000000..c547c94 --- /dev/null +++ b/src/hooks/use-network-connection.test.tsx @@ -0,0 +1,59 @@ +import { render } from "@testing-library/react"; +import { renderHook } from "@testing-library/react-hooks"; +import { + NetworkConnection, + NetworkInformationUtils, +} from "andculturecode-javascript-core"; +import React from "react"; +import { NetworkConnectionProvider } from "../providers/network-connection-provider"; +import { useNetworkConnection } from "./use-network-connection"; + +// ----------------------------------------------------------------------------------------- +// #region Mocks +// ----------------------------------------------------------------------------------------- + +const getNetworkConnectionMock = jest.spyOn( + NetworkInformationUtils, + "getNetworkConnection" +); + +// #endregion Mocks + +describe("useNetworkConnection", () => { + describe("when used outside NetworkConnectionProvider", () => { + it("throws error", () => { + // Arrange & Act + const { result } = renderHook(() => useNetworkConnection()); + + // Assert + expect(result.error).toBeDefined(); + }); + }); + + describe("when used inside NetworkConnectionProvider", () => { + it("returns network connection information", () => { + // Arrange + let networkConnection: NetworkConnection; + const expectedNetworkConnection: NetworkConnection = { + isOnline: true, + }; + + getNetworkConnectionMock.mockReturnValue(expectedNetworkConnection); + + const TestComponent = () => { + networkConnection = useNetworkConnection(); + return
; + }; + + // Act + render( + + + + ); + + // Assert + expect(networkConnection).toEqual(expectedNetworkConnection); + }); + }); +}); diff --git a/src/hooks/use-network-connection.ts b/src/hooks/use-network-connection.ts index b1a2230..7107803 100644 --- a/src/hooks/use-network-connection.ts +++ b/src/hooks/use-network-connection.ts @@ -1,6 +1,18 @@ import { useContext } from "react"; -import { NetworkConnectionContext } from "../providers/network-connection/network-connection-context"; +import { NetworkConnection } from "andculturecode-javascript-core"; +import { NetworkConnectionContext } from "../contexts/network-connection-context"; -export default function useNetworkConnection() { - return useContext(NetworkConnectionContext); -} +/** + * Hook that returns the current network connection information + */ +export const useNetworkConnection = (): NetworkConnection => { + const networkConnection = useContext(NetworkConnectionContext); + + if (networkConnection === undefined) { + throw new Error( + "useNetworkConnection must be used within a NetworkConnectionProvider component" + ); + } + + return networkConnection; +}; diff --git a/src/providers/network-connection/network-connection-provider.test.tsx b/src/providers/network-connection-provider.test.tsx similarity index 95% rename from src/providers/network-connection/network-connection-provider.test.tsx rename to src/providers/network-connection-provider.test.tsx index 380ce40..3b2e396 100644 --- a/src/providers/network-connection/network-connection-provider.test.tsx +++ b/src/providers/network-connection-provider.test.tsx @@ -1,11 +1,11 @@ -import React, { useContext } from "react"; +import React from "react"; import { act, cleanup, render } from "@testing-library/react"; -import NetworkConnectionProvider from "./network-connection-provider"; +import { NetworkConnectionProvider } from "./network-connection-provider"; import { NetworkConnection, NetworkInformationUtils, } from "andculturecode-javascript-core"; -import { NetworkConnectionContext } from "./network-connection-context"; +import { useNetworkConnection } from "../hooks/use-network-connection"; // ----------------------------------------------------------------------------------------- // #region Types @@ -74,7 +74,7 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { }; function TestComponent() { - const connection = useContext(NetworkConnectionContext); + const connection = useNetworkConnection(); networkConnectionResults.all.push(connection); networkConnectionResults.current = connection; diff --git a/src/providers/network-connection/network-connection-provider.tsx b/src/providers/network-connection-provider.tsx similarity index 69% rename from src/providers/network-connection/network-connection-provider.tsx rename to src/providers/network-connection-provider.tsx index a703f93..815d3a6 100644 --- a/src/providers/network-connection/network-connection-provider.tsx +++ b/src/providers/network-connection-provider.tsx @@ -1,11 +1,23 @@ +import React, { + PropsWithChildren, + useCallback, + useEffect, + useState, +} from "react"; import { NetworkConnection, NetworkInformationUtils, } from "andculturecode-javascript-core"; -import React, { useCallback, useEffect, useState } from "react"; -import { NetworkConnectionContext } from "./network-connection-context"; +import { NetworkConnectionContext } from "../contexts/network-connection-context"; + +/** + * Wrapper provider component that provides context to the `useNetworkConnection` hook + */ +export const NetworkConnectionProvider: React.FC = ( + props: PropsWithChildren +) => { + const { children } = props; -const NetworkConnectionProvider: React.FC = ({ children }) => { const [state, setState] = useState( NetworkInformationUtils.getNetworkConnection() ); @@ -26,7 +38,7 @@ const NetworkConnectionProvider: React.FC = ({ children }) => { loadNetworkInformation(); - return () => { + return function cleanup() { networkConnection?.removeEventListener?.( "change", loadNetworkInformation @@ -40,5 +52,3 @@ const NetworkConnectionProvider: React.FC = ({ children }) => { ); }; - -export default NetworkConnectionProvider; diff --git a/src/providers/network-connection/network-connection-context.ts b/src/providers/network-connection/network-connection-context.ts deleted file mode 100644 index 56afa82..0000000 --- a/src/providers/network-connection/network-connection-context.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { NetworkConnection } from "andculturecode-javascript-core"; -import React from "react"; - -export const NetworkConnectionContext = React.createContext({ - isOnline: true, -}); From 73f02dade95d2ed7ca9a2f3157f23fe2b753fd67 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Tue, 22 Jun 2021 15:35:24 -0400 Subject: [PATCH 06/14] export network connection provider and hook --- src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.ts b/src/index.ts index f9ecc62..e132a1f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,6 +18,7 @@ export { NestedRoutesByProperty, NestedRoutesByPropertyProps, } from "./components/routing/nested-routes-by-property"; +export { NetworkConnectionProvider } from "./providers/network-connection-provider"; export { Redirects, RedirectsProps } from "./components/routing/redirects"; // #endregion Components @@ -31,6 +32,7 @@ export { useAsyncEffect } from "./hooks/use-async-effect"; export { useCancellablePromise } from "./hooks/use-cancellable-promise"; export { useDebounce } from "./hooks/use-debounce"; export { useLocalization } from "./hooks/use-localization"; +export { useNetworkConnection } from "./hooks/use-network-connection"; export { useOnClickOutside } from "./hooks/use-onclick-outside"; export { usePageErrors } from "./hooks/use-page-errors"; export { useSortedAlphabetically } from "./hooks/use-sorted-alphabetically"; From 08b3832573f5b9be7f1852afe268e76b3b794c19 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Tue, 22 Jun 2021 16:29:11 -0400 Subject: [PATCH 07/14] additional window eventhandlers --- src/providers/network-connection-provider.tsx | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/providers/network-connection-provider.tsx b/src/providers/network-connection-provider.tsx index 815d3a6..156b718 100644 --- a/src/providers/network-connection-provider.tsx +++ b/src/providers/network-connection-provider.tsx @@ -18,33 +18,62 @@ export const NetworkConnectionProvider: React.FC = ( ) => { const { children } = props; - const [state, setState] = useState( + const [state, setState] = useState( NetworkInformationUtils.getNetworkConnection() ); const loadNetworkInformation = useCallback(() => { const networkConnection = NetworkInformationUtils.getNetworkConnection(); + if (networkConnection == null) { + return; + } + setState((prev) => ({ ...prev, ...networkConnection, })); }, []); - useEffect(() => { - const networkConnection = NetworkInformationUtils.getNetworkConnection(); + useEffect(function handleOnlineOfflineEvents() { + const createNetworkChangeHandler = (isOnline: boolean) => () => { + setState((prev) => ({ + ...prev, + isOnline, + })); + }; - networkConnection?.addEventListener?.("change", loadNetworkInformation); + const handleOffline = createNetworkChangeHandler(false); + const handleOnline = createNetworkChangeHandler(true); - loadNetworkInformation(); + window?.addEventListener?.("online", handleOnline); + window?.addEventListener?.("offline", handleOffline); return function cleanup() { - networkConnection?.removeEventListener?.( + window?.removeEventListener?.("online", handleOnline); + window?.removeEventListener?.("offline", handleOffline); + }; + }, []); + + useEffect( + function handleNetworkChangeEvents() { + const networkConnection = NetworkInformationUtils.getNetworkConnection(); + networkConnection?.addEventListener?.( "change", loadNetworkInformation ); - }; - }, [loadNetworkInformation]); + + loadNetworkInformation(); + + return function cleanup() { + networkConnection?.removeEventListener?.( + "change", + loadNetworkInformation + ); + }; + }, + [loadNetworkInformation] + ); return ( From f85783d0777637c6102c53082f8570492086bf90 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Wed, 23 Jun 2021 14:01:17 -0400 Subject: [PATCH 08/14] update tests --- .../network-connection-provider.test.tsx | 56 +++++++++++-------- .../factories/network-connection-factory.ts | 16 ++++++ 2 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 src/tests/factories/network-connection-factory.ts diff --git a/src/providers/network-connection-provider.test.tsx b/src/providers/network-connection-provider.test.tsx index 3b2e396..cfbe479 100644 --- a/src/providers/network-connection-provider.test.tsx +++ b/src/providers/network-connection-provider.test.tsx @@ -6,6 +6,7 @@ import { NetworkInformationUtils, } from "andculturecode-javascript-core"; import { useNetworkConnection } from "../hooks/use-network-connection"; +import { networkConnectionFactory } from "../tests/factories/network-connection-factory"; // ----------------------------------------------------------------------------------------- // #region Types @@ -48,9 +49,10 @@ const getNetworkConnectionMock = jest.spyOn( // #region Setup // ----------------------------------------------------------------------------------------- -const setupSut = (options?: SetupSutOptions): SetupSutResults => { - const { mockConnections = [] } = options ?? {}; - +const setupMocks = ( + getNetworkConnectionMock: jest.SpyInstance, + mockConnections: Array> +) => { getNetworkConnectionMock.mockReset(); for (let index = 0; index < mockConnections.length; index++) { const mockImplementation = @@ -65,6 +67,12 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { }; }); } +}; + +const setupSut = (options?: SetupSutOptions): SetupSutResults => { + const { mockConnections = [] } = options ?? {}; + + setupMocks(getNetworkConnectionMock, mockConnections); const networkConnectionResults: TypeFromKey< SetupSutResults, @@ -92,11 +100,10 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { describe("NetworkConnectionProvider", () => { it("renders initial network connection state", () => { // Arrange - const connection: NetworkConnection = { - isOnline: true, - }; + const firstConnection = networkConnectionFactory.build(); + const secondConnection = networkConnectionFactory.build(); const { networkConnectionResults, TestComponent } = setupSut({ - mockConnections: [connection], + mockConnections: [firstConnection, secondConnection], }); // Act @@ -108,14 +115,17 @@ describe("NetworkConnectionProvider", () => { // Assert expect(networkConnectionResults.all.length).toEqual(2); - expect(networkConnectionResults.current).toEqual(connection); + expect(networkConnectionResults.current).toEqual(secondConnection); }); it("adds an event listener", () => { // Arrange const addEventListener = jest.fn(); + const networkConnection = networkConnectionFactory.build({ + addEventListener, + }); const { TestComponent } = setupSut({ - mockConnections: [{ addEventListener }], + mockConnections: [networkConnection], }); // Act @@ -132,24 +142,21 @@ describe("NetworkConnectionProvider", () => { describe("when change event is called", () => { it("loads network connection into state", () => { // Arrange - let loadNetworkInformationCallback = () => {}; + let changeEventCallback = () => {}; + + const expectedNetworkConnection = networkConnectionFactory.build(); const mockConnections: Array = [ - { - isOnline: true, - }, - { - isOnline: true, + networkConnectionFactory.build(), + networkConnectionFactory.build({ addEventListener: ( event: "change", callback: VoidFunction ) => { - loadNetworkInformationCallback = callback; + changeEventCallback = callback; }, - }, - { - isOnline: false, - }, + }), + expectedNetworkConnection, ]; const { networkConnectionResults, TestComponent } = setupSut({ @@ -163,14 +170,14 @@ describe("NetworkConnectionProvider", () => { ); - act(() => loadNetworkInformationCallback()); + act(() => changeEventCallback()); // Assert expect(networkConnectionResults.all.length).toEqual( mockConnections.length ); expect(networkConnectionResults.current).toEqual( - mockConnections[2] + expectedNetworkConnection ); }); }); @@ -179,8 +186,11 @@ describe("NetworkConnectionProvider", () => { it("calls removeEventlistener for cleanup", async () => { // Arrange const removeEventListener = jest.fn(); + const networkConnection = networkConnectionFactory.build({ + removeEventListener, + }); const { TestComponent } = setupSut({ - mockConnections: [{ removeEventListener }], + mockConnections: [networkConnection], }); // Act diff --git a/src/tests/factories/network-connection-factory.ts b/src/tests/factories/network-connection-factory.ts new file mode 100644 index 0000000..a3a8598 --- /dev/null +++ b/src/tests/factories/network-connection-factory.ts @@ -0,0 +1,16 @@ +import { NetworkConnection } from "andculturecode-javascript-core"; +import { Factory } from "rosie"; + +// ----------------------------------------------------------------------------------------- +// #region Factory +// ----------------------------------------------------------------------------------------- + +export const networkConnectionFactory = Factory.define< + NetworkConnection & { id: number } +>("NetworkConnection") + .sequence("id") + .attr("isOnline", true) + .attr("addEventListener", () => {}) + .attr("removeEventListener", () => {}); + +// #endregion Factory From b3f50d517b21f0459ca1c09cb1a1043ea9f4a83c Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Wed, 23 Jun 2021 22:59:12 -0400 Subject: [PATCH 09/14] tests cleanup --- .../network-connection-provider.test.tsx | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/providers/network-connection-provider.test.tsx b/src/providers/network-connection-provider.test.tsx index cfbe479..3379af9 100644 --- a/src/providers/network-connection-provider.test.tsx +++ b/src/providers/network-connection-provider.test.tsx @@ -35,7 +35,7 @@ interface SetupSutResults { // #endregion Interfaces // ----------------------------------------------------------------------------------------- -// #region Mocks +// #region Setup // ----------------------------------------------------------------------------------------- const getNetworkConnectionMock = jest.spyOn( @@ -43,16 +43,7 @@ const getNetworkConnectionMock = jest.spyOn( "getNetworkConnection" ); -// #endregion Mocks - -// ----------------------------------------------------------------------------------------- -// #region Setup -// ----------------------------------------------------------------------------------------- - -const setupMocks = ( - getNetworkConnectionMock: jest.SpyInstance, - mockConnections: Array> -) => { +const setupMocks = (mockConnections: Array>) => { getNetworkConnectionMock.mockReset(); for (let index = 0; index < mockConnections.length; index++) { const mockImplementation = @@ -72,7 +63,7 @@ const setupMocks = ( const setupSut = (options?: SetupSutOptions): SetupSutResults => { const { mockConnections = [] } = options ?? {}; - setupMocks(getNetworkConnectionMock, mockConnections); + setupMocks(mockConnections); const networkConnectionResults: TypeFromKey< SetupSutResults, @@ -100,10 +91,12 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { describe("NetworkConnectionProvider", () => { it("renders initial network connection state", () => { // Arrange - const firstConnection = networkConnectionFactory.build(); - const secondConnection = networkConnectionFactory.build(); + const expectedConnection = networkConnectionFactory.build(); const { networkConnectionResults, TestComponent } = setupSut({ - mockConnections: [firstConnection, secondConnection], + mockConnections: [ + networkConnectionFactory.build(), + expectedConnection, + ], }); // Act @@ -115,7 +108,7 @@ describe("NetworkConnectionProvider", () => { // Assert expect(networkConnectionResults.all.length).toEqual(2); - expect(networkConnectionResults.current).toEqual(secondConnection); + expect(networkConnectionResults.current).toEqual(expectedConnection); }); it("adds an event listener", () => { From 537c98bfc94766d85a173f7bbb22a978c385f17c Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Thu, 24 Jun 2021 17:37:20 -0400 Subject: [PATCH 10/14] consolidate the network change event --- src/providers/network-connection-provider.tsx | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/providers/network-connection-provider.tsx b/src/providers/network-connection-provider.tsx index 156b718..77772f0 100644 --- a/src/providers/network-connection-provider.tsx +++ b/src/providers/network-connection-provider.tsx @@ -22,7 +22,7 @@ export const NetworkConnectionProvider: React.FC = ( NetworkInformationUtils.getNetworkConnection() ); - const loadNetworkInformation = useCallback(() => { + const loadNetworkInformation = useCallback((isOnline?: boolean) => { const networkConnection = NetworkInformationUtils.getNetworkConnection(); if (networkConnection == null) { @@ -32,44 +32,37 @@ export const NetworkConnectionProvider: React.FC = ( setState((prev) => ({ ...prev, ...networkConnection, + isOnline: isOnline ?? networkConnection.isOnline, })); }, []); - useEffect(function handleOnlineOfflineEvents() { - const createNetworkChangeHandler = (isOnline: boolean) => () => { - setState((prev) => ({ - ...prev, - isOnline, - })); - }; - - const handleOffline = createNetworkChangeHandler(false); - const handleOnline = createNetworkChangeHandler(true); - - window?.addEventListener?.("online", handleOnline); - window?.addEventListener?.("offline", handleOffline); - - return function cleanup() { - window?.removeEventListener?.("online", handleOnline); - window?.removeEventListener?.("offline", handleOffline); - }; - }, []); - useEffect( function handleNetworkChangeEvents() { const networkConnection = NetworkInformationUtils.getNetworkConnection(); + + const createNetworkChangeHandler = (isOnline?: boolean) => () => + loadNetworkInformation(isOnline); + + const handleNetworkChange = createNetworkChangeHandler(); + const handleOffline = createNetworkChangeHandler(false); + const handleOnline = createNetworkChangeHandler(true); + networkConnection?.addEventListener?.( "change", - loadNetworkInformation + handleNetworkChange ); + window?.addEventListener?.("online", handleOnline); + window?.addEventListener?.("offline", handleOffline); loadNetworkInformation(); return function cleanup() { networkConnection?.removeEventListener?.( "change", - loadNetworkInformation + handleNetworkChange ); + window?.removeEventListener?.("online", handleOnline); + window?.removeEventListener?.("offline", handleOffline); }; }, [loadNetworkInformation] From 3b68f270723439043213c40c64bb61fa209c4422 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Fri, 25 Jun 2021 07:11:13 -0400 Subject: [PATCH 11/14] cleanup around the NetworkConnectionFactory --- src/hooks/use-network-connection.ts | 2 +- .../network-connection-provider.test.tsx | 16 +++++----- src/tests/factories/index.ts | 1 + .../factories/network-connection-factory.ts | 32 +++++++++++++++---- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/hooks/use-network-connection.ts b/src/hooks/use-network-connection.ts index 7107803..77e4d61 100644 --- a/src/hooks/use-network-connection.ts +++ b/src/hooks/use-network-connection.ts @@ -8,7 +8,7 @@ import { NetworkConnectionContext } from "../contexts/network-connection-context export const useNetworkConnection = (): NetworkConnection => { const networkConnection = useContext(NetworkConnectionContext); - if (networkConnection === undefined) { + if (networkConnection == null) { throw new Error( "useNetworkConnection must be used within a NetworkConnectionProvider component" ); diff --git a/src/providers/network-connection-provider.test.tsx b/src/providers/network-connection-provider.test.tsx index 3379af9..209a933 100644 --- a/src/providers/network-connection-provider.test.tsx +++ b/src/providers/network-connection-provider.test.tsx @@ -6,7 +6,7 @@ import { NetworkInformationUtils, } from "andculturecode-javascript-core"; import { useNetworkConnection } from "../hooks/use-network-connection"; -import { networkConnectionFactory } from "../tests/factories/network-connection-factory"; +import { NetworkConnectionFactory } from "../tests/factories/network-connection-factory"; // ----------------------------------------------------------------------------------------- // #region Types @@ -91,10 +91,10 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { describe("NetworkConnectionProvider", () => { it("renders initial network connection state", () => { // Arrange - const expectedConnection = networkConnectionFactory.build(); + const expectedConnection = NetworkConnectionFactory.build(); const { networkConnectionResults, TestComponent } = setupSut({ mockConnections: [ - networkConnectionFactory.build(), + NetworkConnectionFactory.build(), expectedConnection, ], }); @@ -114,7 +114,7 @@ describe("NetworkConnectionProvider", () => { it("adds an event listener", () => { // Arrange const addEventListener = jest.fn(); - const networkConnection = networkConnectionFactory.build({ + const networkConnection = NetworkConnectionFactory.build({ addEventListener, }); const { TestComponent } = setupSut({ @@ -137,11 +137,11 @@ describe("NetworkConnectionProvider", () => { // Arrange let changeEventCallback = () => {}; - const expectedNetworkConnection = networkConnectionFactory.build(); + const expectedNetworkConnection = NetworkConnectionFactory.build(); const mockConnections: Array = [ - networkConnectionFactory.build(), - networkConnectionFactory.build({ + NetworkConnectionFactory.build(), + NetworkConnectionFactory.build({ addEventListener: ( event: "change", callback: VoidFunction @@ -179,7 +179,7 @@ describe("NetworkConnectionProvider", () => { it("calls removeEventlistener for cleanup", async () => { // Arrange const removeEventListener = jest.fn(); - const networkConnection = networkConnectionFactory.build({ + const networkConnection = NetworkConnectionFactory.build({ removeEventListener, }); const { TestComponent } = setupSut({ diff --git a/src/tests/factories/index.ts b/src/tests/factories/index.ts index 65eb52c..26f68cb 100644 --- a/src/tests/factories/index.ts +++ b/src/tests/factories/index.ts @@ -4,3 +4,4 @@ export { } from "./route-definition-factory"; export { RouteMapFactory } from "./route-map-factory"; export { StubResourceRecordFactory } from "andculturecode-javascript-testing"; +export { NetworkConnectionFactory } from "./network-connection-factory"; diff --git a/src/tests/factories/network-connection-factory.ts b/src/tests/factories/network-connection-factory.ts index a3a8598..cd4bdba 100644 --- a/src/tests/factories/network-connection-factory.ts +++ b/src/tests/factories/network-connection-factory.ts @@ -1,16 +1,36 @@ import { NetworkConnection } from "andculturecode-javascript-core"; import { Factory } from "rosie"; +import faker from "faker"; // ----------------------------------------------------------------------------------------- // #region Factory // ----------------------------------------------------------------------------------------- -export const networkConnectionFactory = Factory.define< - NetworkConnection & { id: number } ->("NetworkConnection") - .sequence("id") +export const NetworkConnectionFactory = Factory.define( + "NetworkConnection" +) + .attr("rtt", rttFactory) .attr("isOnline", true) - .attr("addEventListener", () => {}) - .attr("removeEventListener", () => {}); + .attr("addEventListener", eventListenerFactory) + .attr("removeEventListener", eventListenerFactory); // #endregion Factory + +// ----------------------------------------------------------------------------------------- +// #region Functions +// ----------------------------------------------------------------------------------------- + +function eventListenerFactory() { + return () => {}; +} + +/** + * Returns a random estimated effective round-trip time of the current connection, + * rounded to the nearest multiple of 25 milliseconds. Values will range from 25 - 1000 ms. + * https://wicg.github.io/netinfo/#networkinformation-interface + */ +function rttFactory() { + return 25 * (faker.random.number(39) + 1); +} + +// #endregion Functions From 2d2506b5e895b7b91f6ffe167c7f3179ef308483 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Fri, 25 Jun 2021 07:15:33 -0400 Subject: [PATCH 12/14] remove rtt attrinute from NetworkConnectionFactory --- src/tests/factories/network-connection-factory.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/tests/factories/network-connection-factory.ts b/src/tests/factories/network-connection-factory.ts index cd4bdba..49acee3 100644 --- a/src/tests/factories/network-connection-factory.ts +++ b/src/tests/factories/network-connection-factory.ts @@ -1,6 +1,5 @@ import { NetworkConnection } from "andculturecode-javascript-core"; import { Factory } from "rosie"; -import faker from "faker"; // ----------------------------------------------------------------------------------------- // #region Factory @@ -9,7 +8,6 @@ import faker from "faker"; export const NetworkConnectionFactory = Factory.define( "NetworkConnection" ) - .attr("rtt", rttFactory) .attr("isOnline", true) .attr("addEventListener", eventListenerFactory) .attr("removeEventListener", eventListenerFactory); @@ -24,13 +22,4 @@ function eventListenerFactory() { return () => {}; } -/** - * Returns a random estimated effective round-trip time of the current connection, - * rounded to the nearest multiple of 25 milliseconds. Values will range from 25 - 1000 ms. - * https://wicg.github.io/netinfo/#networkinformation-interface - */ -function rttFactory() { - return 25 * (faker.random.number(39) + 1); -} - // #endregion Functions From 19b0bbb10502b9f7d820424e7e301a0b94e35649 Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Fri, 25 Jun 2021 07:41:25 -0400 Subject: [PATCH 13/14] more test factory cleanup --- .../network-connection-provider.test.tsx | 52 ++++++++++++------- src/tests/factories/factory-type.ts | 1 + .../factories/network-connection-factory.ts | 3 +- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/providers/network-connection-provider.test.tsx b/src/providers/network-connection-provider.test.tsx index 209a933..f03813b 100644 --- a/src/providers/network-connection-provider.test.tsx +++ b/src/providers/network-connection-provider.test.tsx @@ -6,7 +6,8 @@ import { NetworkInformationUtils, } from "andculturecode-javascript-core"; import { useNetworkConnection } from "../hooks/use-network-connection"; -import { NetworkConnectionFactory } from "../tests/factories/network-connection-factory"; +import { FactoryType } from "../tests/factories/factory-type"; +import { Factory } from "rosie"; // ----------------------------------------------------------------------------------------- // #region Types @@ -91,10 +92,12 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { describe("NetworkConnectionProvider", () => { it("renders initial network connection state", () => { // Arrange - const expectedConnection = NetworkConnectionFactory.build(); + const expectedConnection = Factory.build( + FactoryType.NetworkConnection + ); const { networkConnectionResults, TestComponent } = setupSut({ mockConnections: [ - NetworkConnectionFactory.build(), + Factory.build(FactoryType.NetworkConnection), expectedConnection, ], }); @@ -114,9 +117,12 @@ describe("NetworkConnectionProvider", () => { it("adds an event listener", () => { // Arrange const addEventListener = jest.fn(); - const networkConnection = NetworkConnectionFactory.build({ - addEventListener, - }); + const networkConnection = Factory.build( + FactoryType.NetworkConnection, + { + addEventListener, + } + ); const { TestComponent } = setupSut({ mockConnections: [networkConnection], }); @@ -137,18 +143,23 @@ describe("NetworkConnectionProvider", () => { // Arrange let changeEventCallback = () => {}; - const expectedNetworkConnection = NetworkConnectionFactory.build(); + const expectedNetworkConnection = Factory.build( + FactoryType.NetworkConnection + ); const mockConnections: Array = [ - NetworkConnectionFactory.build(), - NetworkConnectionFactory.build({ - addEventListener: ( - event: "change", - callback: VoidFunction - ) => { - changeEventCallback = callback; - }, - }), + Factory.build(FactoryType.NetworkConnection), + Factory.build( + FactoryType.NetworkConnection, + { + addEventListener: ( + event: "change", + callback: VoidFunction + ) => { + changeEventCallback = callback; + }, + } + ), expectedNetworkConnection, ]; @@ -179,9 +190,12 @@ describe("NetworkConnectionProvider", () => { it("calls removeEventlistener for cleanup", async () => { // Arrange const removeEventListener = jest.fn(); - const networkConnection = NetworkConnectionFactory.build({ - removeEventListener, - }); + const networkConnection = Factory.build( + FactoryType.NetworkConnection, + { + removeEventListener, + } + ); const { TestComponent } = setupSut({ mockConnections: [networkConnection], }); diff --git a/src/tests/factories/factory-type.ts b/src/tests/factories/factory-type.ts index 6b72648..13c1c38 100644 --- a/src/tests/factories/factory-type.ts +++ b/src/tests/factories/factory-type.ts @@ -1,4 +1,5 @@ const FactoryType = { + NetworkConnection: "NetworkConnection", RouteDefinition: { Default: "RouteDefinition", Nested: "RouteDefinition.Nested", diff --git a/src/tests/factories/network-connection-factory.ts b/src/tests/factories/network-connection-factory.ts index 49acee3..c60e361 100644 --- a/src/tests/factories/network-connection-factory.ts +++ b/src/tests/factories/network-connection-factory.ts @@ -1,12 +1,13 @@ import { NetworkConnection } from "andculturecode-javascript-core"; import { Factory } from "rosie"; +import { FactoryType } from "./factory-type"; // ----------------------------------------------------------------------------------------- // #region Factory // ----------------------------------------------------------------------------------------- export const NetworkConnectionFactory = Factory.define( - "NetworkConnection" + FactoryType.NetworkConnection ) .attr("isOnline", true) .attr("addEventListener", eventListenerFactory) From a4548a508157a8482217bc68ada6f23bc87fc8ae Mon Sep 17 00:00:00 2001 From: Michael Tyson Date: Fri, 25 Jun 2021 08:27:48 -0400 Subject: [PATCH 14/14] update util type to TypeOfKey --- src/providers/network-connection-provider.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/network-connection-provider.test.tsx b/src/providers/network-connection-provider.test.tsx index f03813b..c58d59a 100644 --- a/src/providers/network-connection-provider.test.tsx +++ b/src/providers/network-connection-provider.test.tsx @@ -13,7 +13,7 @@ import { Factory } from "rosie"; // #region Types // ----------------------------------------------------------------------------------------- -type TypeFromKey = Type[Key]; +type TypeOfKey = Type[Key]; // #endregion Types @@ -66,7 +66,7 @@ const setupSut = (options?: SetupSutOptions): SetupSutResults => { setupMocks(mockConnections); - const networkConnectionResults: TypeFromKey< + const networkConnectionResults: TypeOfKey< SetupSutResults, "networkConnectionResults" > = {