From ff5cb2120f154a605c15bdaa8ae70923f31b90b0 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 4 Dec 2023 09:16:16 +0000 Subject: [PATCH 1/3] chore: react lib testing --- packages/dapp-kit-react/README.md | 58 ++++---- packages/dapp-kit-react/package.json | 8 +- .../ConnectWalletModal/ConnectWalletModal.tsx | 4 +- .../SelectWalletModal/SelectWalletModal.tsx | 4 +- .../dapp-kit-react/src/DAppKitProvider.tsx | 13 +- .../test/helpers/react-test-helpers.tsx | 15 ++ .../test/provider/ThemeProvider.test.tsx | 23 +++ packages/dapp-kit-react/test/setup/setup.ts | 28 ++++ .../dapp-kit-react/test/useConnex.test.tsx | 16 ++ .../dapp-kit-react/test/useWallet.test.tsx | 18 +++ .../test/useWalletModal.test.tsx | 20 +++ packages/dapp-kit-react/vite.config.ts | 28 ++++ .../components/connect-button-with-modal.ts | 13 +- .../test/connect-button-with-modal.test.ts | 1 - packages/dapp-kit/src/wallet-manager.ts | 29 +++- yarn.lock | 138 ++++++++++++++++-- 16 files changed, 352 insertions(+), 64 deletions(-) create mode 100644 packages/dapp-kit-react/test/helpers/react-test-helpers.tsx create mode 100644 packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx create mode 100644 packages/dapp-kit-react/test/setup/setup.ts create mode 100644 packages/dapp-kit-react/test/useConnex.test.tsx create mode 100644 packages/dapp-kit-react/test/useWallet.test.tsx create mode 100644 packages/dapp-kit-react/test/useWalletModal.test.tsx create mode 100644 packages/dapp-kit-react/vite.config.ts diff --git a/packages/dapp-kit-react/README.md b/packages/dapp-kit-react/README.md index d407a772..5e38705e 100644 --- a/packages/dapp-kit-react/README.md +++ b/packages/dapp-kit-react/README.md @@ -23,50 +23,48 @@ yarn build yarn add @vechainfoundation/dapp-kit-react ``` -```typescript -import type { Options } from '@vechain/connex'; - -const nodeOptions: Omit = { - node: 'https://testnet.vechain.org/', - network: 'test', -}; -``` - - Optional: Configure wallet connect options ```typescript -import type { WalletConnectOptions } from '@vechainfoundation/dapp-kit'; +import type { WalletConnectOptions } from '@vechain/dapp-kit'; const walletConnectOptions: WalletConnectOptions = { - projectId: '', // Create your project here: https://cloud.walletconnect.com/sign-up + // Create your project here: https://cloud.walletconnect.com/sign-up + projectId: '', metadata: { name: 'My dApp', description: 'My dApp description', - url: window.location.origin, // Your app URL - icons: [`${window.location.origin}/images/my-dapp-icon.png`], // Your app Icon + // Your app URL + url: window.location.origin, + // Your app Icon + icons: [`${window.location.origin}/images/my-dapp-icon.png`], }, }; ``` -- Initialise the `ConnexVendor` +- Initialise the `DAppKitProvider` ```typescript jsx -import { DAppKitProvider } from '@vechainfoundation/dapp-kit-react'; - -export const App = (): JSX.Element => { - return ( - <> - - - - - ); -}; +import { DAppKitProvider } from '@vechain/dapp-kit-react'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + , +); ``` - Use the hooks provided by the `DAppKitProvider` diff --git a/packages/dapp-kit-react/package.json b/packages/dapp-kit-react/package.json index 48f1033c..2062c328 100644 --- a/packages/dapp-kit-react/package.json +++ b/packages/dapp-kit-react/package.json @@ -18,7 +18,8 @@ "clean": "rm -rf dist .turbo", "dev": "tsup src/index.tsx --format esm --watch --dts --external react", "lint": "tsc --noEmit && eslint src --ext .js,.jsx,.ts,.tsx", - "purge": "yarn clean && rm -rf node_modules" + "purge": "yarn clean && rm -rf node_modules", + "test": "vitest run --coverage" }, "dependencies": { "@heroicons/react": "^2.0.18", @@ -34,12 +35,15 @@ "valtio": "^1.12.1" }, "devDependencies": { + "@testing-library/react": "^14.1.2", "@types/react": "^18.2.28", "@types/react-dom": "^18.2.13", "@vechain/repo-config": "https://github.com/vechainfoundation/repo-config#v0.0.1", "eslint": "*", "react": "^18.2.0", "tsup": "*", - "typescript": "*" + "typescript": "*", + "vite": "^4.5.0", + "vitest": "^0.34.6" } } diff --git a/packages/dapp-kit-react/src/Components/ConnectWalletModal/ConnectWalletModal.tsx b/packages/dapp-kit-react/src/Components/ConnectWalletModal/ConnectWalletModal.tsx index 8cff8532..8afbc6d6 100644 --- a/packages/dapp-kit-react/src/Components/ConnectWalletModal/ConnectWalletModal.tsx +++ b/packages/dapp-kit-react/src/Components/ConnectWalletModal/ConnectWalletModal.tsx @@ -15,6 +15,7 @@ const createButtonWithModal = () => interface ConnectWalletProps { onConnectError?: (err: unknown) => void; onConnected?: (res: ConnectResponse) => void; + isOpen: boolean; } /** @@ -26,6 +27,7 @@ interface ConnectWalletProps { export const ConnectWalletModal: React.FC = ({ onConnectError, onConnected, + isOpen, }) => { const Modal = useMemo(() => createButtonWithModal(), []); @@ -41,5 +43,5 @@ export const ConnectWalletModal: React.FC = ({ [onConnectError, onConnected, connect, setSource], ); - return ; + return ; }; diff --git a/packages/dapp-kit-react/src/Components/SelectWalletModal/SelectWalletModal.tsx b/packages/dapp-kit-react/src/Components/SelectWalletModal/SelectWalletModal.tsx index 732b36dd..555c3ef8 100644 --- a/packages/dapp-kit-react/src/Components/SelectWalletModal/SelectWalletModal.tsx +++ b/packages/dapp-kit-react/src/Components/SelectWalletModal/SelectWalletModal.tsx @@ -14,6 +14,7 @@ const createButtonWithModal = () => interface SelectWalletProps { onSelected?: (source: WalletSource) => void; + isOpen: boolean; } /** @@ -23,6 +24,7 @@ interface SelectWalletProps { */ export const SelectWalletModal: React.FC = ({ onSelected, + isOpen, }) => { const Modal = useMemo(() => createButtonWithModal(), []); @@ -38,5 +40,5 @@ export const SelectWalletModal: React.FC = ({ [onSelected, setSource], ); - return ; + return ; }; diff --git a/packages/dapp-kit-react/src/DAppKitProvider.tsx b/packages/dapp-kit-react/src/DAppKitProvider.tsx index 446e14ef..0976bea0 100644 --- a/packages/dapp-kit-react/src/DAppKitProvider.tsx +++ b/packages/dapp-kit-react/src/DAppKitProvider.tsx @@ -45,8 +45,17 @@ export const DAppKitProvider: React.FC = ({ ); useEffect(() => { - subscribeKey(connex.wallet.state, 'address', (v) => setAccount(v)); - subscribeKey(connex.wallet.state, 'source', (v) => setSource(v)); + const addressSub = subscribeKey(connex.wallet.state, 'address', (v) => + setAccount(v), + ); + const sourceSub = subscribeKey(connex.wallet.state, 'source', (v) => + setSource(v), + ); + + return () => { + addressSub(); + sourceSub(); + }; }, [connex.wallet.state]); const openModal = useCallback(() => { diff --git a/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx b/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx new file mode 100644 index 00000000..809c34b3 --- /dev/null +++ b/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx @@ -0,0 +1,15 @@ +import { + ConnectWalletButtonWithModal, + ConnectWalletModal, + DAppKitProvider, + SelectWalletModal, +} from '../../src'; + +export const wrapper = ({ children }: { children?: React.ReactNode }) => ( + + {children} + + + + +); diff --git a/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx b/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx new file mode 100644 index 00000000..6205e132 --- /dev/null +++ b/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx @@ -0,0 +1,23 @@ +import { renderHook, waitFor } from '@testing-library/react'; +import { useContext } from 'react'; +import { describe, expect, it } from 'vitest'; +import { ThemeContext } from '../../src/provider/ThemeProvider'; +import { wrapper } from '../helpers/react-test-helpers'; + +describe('useThemeContext', () => { + it('should be able to toggle themes', async () => { + const { result } = renderHook(() => useContext(ThemeContext), { + wrapper, + }); + + expect(result.current).toBeDefined(); + + expect(result.current.theme).toEqual({ mode: 'LIGHT' }); + + result.current.toggleTheme(); + + await waitFor(() => { + expect(result.current.theme).toEqual({ mode: 'DARK' }); + }); + }); +}); diff --git a/packages/dapp-kit-react/test/setup/setup.ts b/packages/dapp-kit-react/test/setup/setup.ts new file mode 100644 index 00000000..139c0323 --- /dev/null +++ b/packages/dapp-kit-react/test/setup/setup.ts @@ -0,0 +1,28 @@ +import { vi } from 'vitest'; + +vi.mock('@walletconnect/modal'); + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: vi.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: vi.fn(), // deprecated + removeListener: vi.fn(), // deprecated + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + dispatchEvent: vi.fn(), + })), +}); +global.ResizeObserver = class ResizeObserver { + observe() { + // do nothing + } + unobserve() { + // do nothing + } + disconnect() { + // do nothing + } +}; diff --git a/packages/dapp-kit-react/test/useConnex.test.tsx b/packages/dapp-kit-react/test/useConnex.test.tsx new file mode 100644 index 00000000..b8c15e16 --- /dev/null +++ b/packages/dapp-kit-react/test/useConnex.test.tsx @@ -0,0 +1,16 @@ +import { describe, it } from 'vitest'; +import { renderHook } from '@testing-library/react'; +import { useConnex } from '../src'; +import { wrapper } from './helpers/react-test-helpers'; + +describe('useConnex', () => { + it('connex should get initialised', () => { + const { result } = renderHook(() => useConnex(), { wrapper }); + + expect(result.current).toBeDefined(); + + expect(result.current.thor.genesis.id).toBe( + '0x00000000851caf3cfdb6e899cf5958bfb1ac3413d346d43539627e6be7ec1b4a', + ); + }); +}); diff --git a/packages/dapp-kit-react/test/useWallet.test.tsx b/packages/dapp-kit-react/test/useWallet.test.tsx new file mode 100644 index 00000000..372910de --- /dev/null +++ b/packages/dapp-kit-react/test/useWallet.test.tsx @@ -0,0 +1,18 @@ +import { describe, it } from 'vitest'; +import { renderHook, waitFor } from '@testing-library/react'; +import { useWallet } from '../src'; +import { wrapper } from './helpers/react-test-helpers'; + +describe('useWallet', () => { + it('should be able to set the source', async () => { + const { result } = renderHook(() => useWallet(), { wrapper }); + + expect(result.current).toBeDefined(); + + result.current.setSource('sync2'); + + await waitFor(() => { + expect(result.current.source).toBe('sync2'); + }); + }); +}); diff --git a/packages/dapp-kit-react/test/useWalletModal.test.tsx b/packages/dapp-kit-react/test/useWalletModal.test.tsx new file mode 100644 index 00000000..39b29808 --- /dev/null +++ b/packages/dapp-kit-react/test/useWalletModal.test.tsx @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'vitest'; +import { renderHook, waitFor } from '@testing-library/react'; +import { useWalletModal } from '../src'; +import { wrapper } from './helpers/react-test-helpers'; + +describe('useWalletModal', () => { + it('should be able to open the modal', async () => { + const { result } = renderHook(() => useWalletModal(), { wrapper }); + + expect(result.current).toBeDefined(); + + result.current.open(); + + await waitFor(() => { + const modal = window.document.querySelector('vwk-connect-modal'); + + expect(modal).toBeDefined(); + }); + }); +}); diff --git a/packages/dapp-kit-react/vite.config.ts b/packages/dapp-kit-react/vite.config.ts new file mode 100644 index 00000000..32b2c78e --- /dev/null +++ b/packages/dapp-kit-react/vite.config.ts @@ -0,0 +1,28 @@ +/// +import { resolve } from 'node:path'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['test/**/*.test.ts', 'test/**/*.test.tsx'], + environment: 'jsdom', + reporters: 'dot', + setupFiles: [resolve(__dirname, 'test/setup/setup.ts')], + coverage: { + reporter: [ + 'text', + 'json', + 'html', + 'lcov', + 'json-summary', + 'text-summary', + 'text', + ], + lines: 90, + statements: 90, + functions: 90, + branches: 85, + }, + globals: true, + }, +}); diff --git a/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts b/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts index 5c16e1dc..75de14ec 100644 --- a/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts +++ b/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts @@ -49,10 +49,9 @@ export class ConnectButtonWithModal extends LitElement { @property({ type: Function }) onDisconnectClick = (): void => { - this.wallet.disconnect().finally(() => { - this.dappKitContext.address = ''; - this.requestUpdate(); - }); + this.dappKitContext.address = ''; + this.requestUpdate(); + this.wallet.disconnect(); }; override render(): TemplateResult { @@ -84,9 +83,9 @@ export class ConnectButtonWithModal extends LitElement { } private handleOpen = (): void => { - DAppKitUI.wallet.disconnect().finally(() => { - this.open = true; - }); + this.open = false; + DAppKitUI.wallet.disconnect(); + this.requestUpdate(); }; private handleClose = (): void => { diff --git a/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts b/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts index c6293869..1246e073 100644 --- a/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts +++ b/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts @@ -32,7 +32,6 @@ describe('connect-button-with-modal', () => { window.document.body.appendChild(element); // testing the connect button - const connectButton = (await elementQueries.getConnectButton()) as ConnectButton; const connectModal = diff --git a/packages/dapp-kit/src/wallet-manager.ts b/packages/dapp-kit/src/wallet-manager.ts index e2d32135..b58730b7 100644 --- a/packages/dapp-kit/src/wallet-manager.ts +++ b/packages/dapp-kit/src/wallet-manager.ts @@ -79,7 +79,7 @@ class WalletManager { throw e; }); - disconnect = async (remote = false): Promise => { + disconnect = (remote = false): void => { if (!this.state.source) { return; } @@ -93,8 +93,14 @@ class WalletManager { const wallet = this.wallets[this.state.source]; - if (wallet && !remote) { - await wallet.disconnect?.(); + if (wallet && !remote && wallet.disconnect) { + const res = wallet.disconnect(); + + if (res instanceof Promise) { + res.catch((e) => { + DAppKitLogger.error('WalletManager', 'disconnect', e); + }); + } } this.state.source = null; @@ -132,6 +138,14 @@ class WalletManager { }); setSource = (src: WalletSource): void => { + if (this.state.source === src) { + return; + } + + if (this.state.source && this.state.source !== src) { + this.disconnect(); + } + if (src === 'wallet-connect' && !this.options.walletConnectOptions) { throw new Error('WalletConnect options are not provided'); } @@ -146,6 +160,7 @@ class WalletManager { DAppKitLogger.debug('WalletManager', 'setSource', src); + this.disconnect(); this.state.source = src; }; @@ -187,12 +202,12 @@ class WalletManager { }); }; - private initPersistence = (usePersistent: boolean): void => { - if (!usePersistent) { + private initPersistence = (usePersistence: boolean): void => { + if (!usePersistence) { return; } - subscribeKey(this.state, 'address', Storage.setAccount); - subscribeKey(this.state, 'source', Storage.setSource); + this.subscribeToKey('address', Storage.setAccount); + this.subscribeToKey('source', Storage.setSource); }; private getAvailableSources = (): WalletSource[] => { diff --git a/yarn.lock b/yarn.lock index 4efdf748..baaa1431 100644 --- a/yarn.lock +++ b/yarn.lock @@ -263,18 +263,18 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" -"@babel/code-frame@^7.22.5", "@babel/code-frame@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.4.tgz#03ae5af150be94392cb5c7ccd97db5a19a5da6aa" - integrity sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA== +"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: "@babel/highlight" "^7.23.4" chalk "^2.4.2" -"@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== +"@babel/code-frame@^7.22.5", "@babel/code-frame@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.4.tgz#03ae5af150be94392cb5c7ccd97db5a19a5da6aa" + integrity sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA== dependencies: "@babel/highlight" "^7.23.4" chalk "^2.4.2" @@ -1738,6 +1738,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.12.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.5.tgz#11edb98f8aeec529b82b211028177679144242db" + integrity sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -4480,6 +4487,29 @@ resolved "https://registry.yarnpkg.com/@teppeis/multimaps/-/multimaps-2.0.0.tgz#2114ee964b702f9777d0e07899087ad9cd89a0de" integrity sha512-TL1adzq1HdxUf9WYduLcQ/DNGYiz71U31QRgbnr0Ef1cPyOUOsBojxHVWpFeOSUucB6Lrs0LxFRA14ntgtkc9w== +"@testing-library/dom@^9.0.0": + version "9.3.3" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-9.3.3.tgz#108c23a5b0ef51121c26ae92eb3179416b0434f5" + integrity sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^5.0.1" + aria-query "5.1.3" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + pretty-format "^27.0.2" + +"@testing-library/react@^14.1.2": + version "14.1.2" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.1.2.tgz#a2b9e9ee87721ec9ed2d7cfc51cc04e474537c32" + integrity sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg== + dependencies: + "@babel/runtime" "^7.12.5" + "@testing-library/dom" "^9.0.0" + "@types/react-dom" "^18.0.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -4528,6 +4558,11 @@ "@tufjs/canonical-json" "1.0.0" minimatch "^9.0.0" +"@types/aria-query@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== + "@types/babel__core@^7.20.4": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -4827,7 +4862,7 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.6.tgz#7cb33992049fd7340d5b10c0098e104184dfcd2a" integrity sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA== -"@types/react-dom@^18", "@types/react-dom@^18.2.15": +"@types/react-dom@^18", "@types/react-dom@^18.0.0", "@types/react-dom@^18.2.15": version "18.2.17" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.17.tgz#375c55fab4ae671bd98448dcfa153268d01d6f64" integrity sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg== @@ -6641,6 +6676,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" + integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== + dependencies: + deep-equal "^2.0.5" + aria-query@^5.1.3, aria-query@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" @@ -8463,6 +8505,30 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" +deep-equal@^2.0.5: + version "2.2.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.5" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.2" + is-arguments "^1.1.1" + is-array-buffer "^3.0.2" + is-date-object "^1.0.5" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + isarray "^2.0.5" + object-is "^1.1.5" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + side-channel "^1.0.4" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.13" + deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -8693,6 +8759,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -9032,6 +9103,21 @@ es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" +es-get-iterator@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" + integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + is-arguments "^1.1.1" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.7" + isarray "^2.0.5" + stop-iteration-iterator "^1.0.0" + es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" @@ -11192,7 +11278,7 @@ inquirer@8.2.4: through "^2.3.6" wrap-ansi "^7.0.0" -internal-slot@^1.0.5: +internal-slot@^1.0.4, internal-slot@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== @@ -11216,7 +11302,7 @@ ipaddr.js@^2.0.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== -is-arguments@^1.0.4: +is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== @@ -11388,7 +11474,7 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== -is-map@^2.0.1: +is-map@^2.0.1, is-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== @@ -11475,7 +11561,7 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-set@^2.0.1: +is-set@^2.0.1, is-set@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== @@ -12597,6 +12683,11 @@ luxon@3.2.1: resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.2.1.tgz#14f1af209188ad61212578ea7e3d518d18cee45f" integrity sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg== +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + magic-string@0.30.1: version "0.30.1" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.1.tgz#ce5cd4b0a81a5d032bd69aab4522299b2166284d" @@ -14533,6 +14624,15 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + pretty-format@^29.5.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -14803,6 +14903,11 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-is@^18.0.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -15976,6 +16081,13 @@ std-env@^3.3.3: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.5.0.tgz#83010c9e29bd99bf6f605df87c19012d82d63b97" integrity sha512-JGUEaALvL0Mf6JCfYnJOTcobY+Nc7sG/TemDRBqCA0wEr4DER7zDchaaixTlmOxAjG1uRJmX82EQcxwTQTkqVA== +stop-iteration-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" + integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== + dependencies: + internal-slot "^1.0.4" + stream-browserify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" From a7d2639a732f96ee5533ceece2e532fca9f6fc57 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 4 Dec 2023 09:53:31 +0000 Subject: [PATCH 2/3] fix: unit tests --- .../dapp-kit-react/src/provider/ThemeProvider.tsx | 12 +++++------- .../test/helpers/react-test-helpers.tsx | 11 +++++++---- .../test/provider/ThemeProvider.test.tsx | 13 ++++++++----- .../src/components/connect-button-with-modal.ts | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/dapp-kit-react/src/provider/ThemeProvider.tsx b/packages/dapp-kit-react/src/provider/ThemeProvider.tsx index 1a95915b..0507f11d 100644 --- a/packages/dapp-kit-react/src/provider/ThemeProvider.tsx +++ b/packages/dapp-kit-react/src/provider/ThemeProvider.tsx @@ -9,7 +9,7 @@ interface Theme { mode: ThemeMode; } -interface ContextProperties { +interface ThemeContextProperties { theme: Theme; toggleTheme: () => void; } @@ -18,11 +18,9 @@ const defaultTheme: Theme = { mode: 'LIGHT', }; -const ThemeContext = createContext({ - theme: defaultTheme, - // eslint-disable-next-line @typescript-eslint/no-empty-function - toggleTheme: () => {}, -}); +const ThemeContext = createContext( + undefined, +); const ThemeProvider = ({ children }: { children: ReactNode }) => { const [currentTheme, setCurrentTheme] = useState(defaultTheme); @@ -46,4 +44,4 @@ const ThemeProvider = ({ children }: { children: ReactNode }) => { ); }; -export { ThemeProvider, ThemeContext }; +export { ThemeProvider, ThemeContext, type ThemeContextProperties }; diff --git a/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx b/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx index 809c34b3..7425dafb 100644 --- a/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx +++ b/packages/dapp-kit-react/test/helpers/react-test-helpers.tsx @@ -4,12 +4,15 @@ import { DAppKitProvider, SelectWalletModal, } from '../../src'; +import { ThemeProvider } from '../../src/provider/ThemeProvider'; export const wrapper = ({ children }: { children?: React.ReactNode }) => ( - {children} - - - + + {children} + + + + ); diff --git a/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx b/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx index 6205e132..12372eb4 100644 --- a/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx +++ b/packages/dapp-kit-react/test/provider/ThemeProvider.test.tsx @@ -12,12 +12,15 @@ describe('useThemeContext', () => { expect(result.current).toBeDefined(); - expect(result.current.theme).toEqual({ mode: 'LIGHT' }); + expect(result.current?.theme).toEqual({ mode: 'LIGHT' }); - result.current.toggleTheme(); + result.current?.toggleTheme(); - await waitFor(() => { - expect(result.current.theme).toEqual({ mode: 'DARK' }); - }); + await waitFor( + () => { + expect(result.current?.theme).toEqual({ mode: 'DARK' }); + }, + { timeout: 3000 }, + ); }); }); diff --git a/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts b/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts index 75de14ec..7d2d872a 100644 --- a/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts +++ b/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts @@ -83,7 +83,7 @@ export class ConnectButtonWithModal extends LitElement { } private handleOpen = (): void => { - this.open = false; + this.open = true; DAppKitUI.wallet.disconnect(); this.requestUpdate(); }; From c8c482330b27093e5a3c5b886ccde7f084e22808 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 4 Dec 2023 10:04:53 +0000 Subject: [PATCH 3/3] fix: update tests and theme selector --- .../Components/ConnectButtonWithModal.tsx | 6 +++--- .../dapp-kit-react/src/Components/ThemeSelector.tsx | 6 +++--- packages/dapp-kit-react/src/provider/ThemeProvider.tsx | 10 ++++++++++ packages/dapp-kit-react/vite.config.ts | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/dapp-kit-react/src/Components/ConnectWalletButtonWithModal/Components/ConnectButtonWithModal.tsx b/packages/dapp-kit-react/src/Components/ConnectWalletButtonWithModal/Components/ConnectButtonWithModal.tsx index e3c31b53..6492b4ac 100644 --- a/packages/dapp-kit-react/src/Components/ConnectWalletButtonWithModal/Components/ConnectButtonWithModal.tsx +++ b/packages/dapp-kit-react/src/Components/ConnectWalletButtonWithModal/Components/ConnectButtonWithModal.tsx @@ -1,9 +1,9 @@ -import { useContext, useMemo } from 'react'; -import { ThemeContext } from '../../../provider/ThemeProvider'; +import { useMemo } from 'react'; +import { useThemeSelector } from '../../../provider/ThemeProvider'; import { createButtonWithModal } from './Wrapped/ConnectModalWithButtonWrapped'; export const ConnectButtonWithModal = () => { - const { theme } = useContext(ThemeContext); + const { theme } = useThemeSelector(); const ModalWithButton = useMemo(() => createButtonWithModal(), []); diff --git a/packages/dapp-kit-react/src/Components/ThemeSelector.tsx b/packages/dapp-kit-react/src/Components/ThemeSelector.tsx index af7fa8ee..a0c0d700 100644 --- a/packages/dapp-kit-react/src/Components/ThemeSelector.tsx +++ b/packages/dapp-kit-react/src/Components/ThemeSelector.tsx @@ -1,14 +1,14 @@ // ThemeSelector.js -import React, { useContext } from 'react'; +import React from 'react'; // eslint-disable-next-line import/no-named-as-default import styled from 'styled-components'; -import { ThemeContext } from '../provider/ThemeProvider'; +import { useThemeSelector } from '../provider/ThemeProvider'; const Button = styled.button``; const ThemeSelector = () => { - const { toggleTheme } = useContext(ThemeContext); + const { toggleTheme } = useThemeSelector(); return ; }; diff --git a/packages/dapp-kit-react/src/provider/ThemeProvider.tsx b/packages/dapp-kit-react/src/provider/ThemeProvider.tsx index 0507f11d..4c546d9d 100644 --- a/packages/dapp-kit-react/src/provider/ThemeProvider.tsx +++ b/packages/dapp-kit-react/src/provider/ThemeProvider.tsx @@ -44,4 +44,14 @@ const ThemeProvider = ({ children }: { children: ReactNode }) => { ); }; +export const useThemeSelector = (): ThemeContextProperties => { + const context = React.useContext(ThemeContext); + + if (context === undefined) { + throw new Error('useThemeSelector must be used within a ThemeProvider'); + } + + return context; +}; + export { ThemeProvider, ThemeContext, type ThemeContextProperties }; diff --git a/packages/dapp-kit-react/vite.config.ts b/packages/dapp-kit-react/vite.config.ts index 32b2c78e..93c96b7d 100644 --- a/packages/dapp-kit-react/vite.config.ts +++ b/packages/dapp-kit-react/vite.config.ts @@ -21,7 +21,7 @@ export default defineConfig({ lines: 90, statements: 90, functions: 90, - branches: 85, + branches: 80, }, globals: true, },