From 7683a65cb609de0893b1d7a268ceaf1920108173 Mon Sep 17 00:00:00 2001 From: Swain Molster Date: Thu, 9 Nov 2023 05:44:53 -0500 Subject: [PATCH] feat: add basic test suite for hooks (#600) * chore: add basic test suite for hooks * upgrade @types/react to fix tsc errors --- .github/workflows/validate-js.yml | 27 + babel.config.js | 3 + example/package.json | 2 +- example/yarn.lock | 8 +- package.json | 9 +- test/hooks.test.tsx | 88 ++ yarn.lock | 1506 ++++++++++++++++++++++++++++- 7 files changed, 1613 insertions(+), 30 deletions(-) create mode 100644 babel.config.js create mode 100644 test/hooks.test.tsx diff --git a/.github/workflows/validate-js.yml b/.github/workflows/validate-js.yml index f430c2ba..9eb65fc7 100644 --- a/.github/workflows/validate-js.yml +++ b/.github/workflows/validate-js.yml @@ -104,3 +104,30 @@ jobs: - name: Verify no files have changed after auto-fix run: git diff --exit-code HEAD + + test: + name: Test JS + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - name: Restore node_modules from cache + uses: actions/cache@v2 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install node_modules + run: yarn install --frozen-lockfile + + - name: Install node_modules (example/) + run: yarn install --frozen-lockfile --cwd example + + - name: Run Jest + run: yarn test \ No newline at end of file diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..f842b77f --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], +}; diff --git a/example/package.json b/example/package.json index b304dfdc..408c8575 100644 --- a/example/package.json +++ b/example/package.json @@ -26,7 +26,7 @@ "@react-native-community/eslint-plugin": "^1.3.0", "@tsconfig/react-native": "^2.0.3", "@types/jest": "^29.2.5", - "@types/react": "^18.0.26", + "@types/react": "^18.2.36", "@typescript-eslint/eslint-plugin": "^5.48.1", "babel-plugin-module-resolver": "^5.0.0", "eslint": "^8.32.0", diff --git a/example/yarn.lock b/example/yarn.lock index 2756a5c2..ad399ec9 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -1574,10 +1574,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/react@^18.0.26": - version "18.0.26" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" - integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug== +"@types/react@^18.2.36": + version "18.2.36" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.36.tgz#bc68ffb4408e5d0c419b0760b2eaeec70aeeedb3" + integrity sha512-o9XFsHYLLZ4+sb9CWUYwHqFVoG61SesydF353vFMMsQziiyRu8np4n2OYMUSDZ8XuImxDr9c5tR7gidlH29Vnw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" diff --git a/package.json b/package.json index 7e067d09..7e894914 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "lint": "eslint \"**/*.{js,ts,tsx}\"", "lint-ci": "yarn lint -f ./node_modules/@firmnav/eslint-github-actions-formatter/dist/formatter.js", "lint-cpp": "scripts/clang-format.sh", + "test": "jest", "prepare": "git submodule update --init --recursive && bob build", "prepack": "bob build", "update-submodule": "git submodule update --remote --merge", @@ -61,16 +62,22 @@ "@react-native-community/eslint-config": "^3.2.0", "@react-native-community/eslint-plugin": "^1.3.0", "@release-it/conventional-changelog": "^5.1.1", + "@testing-library/react-native": "^12.3.2", "@tsconfig/react-native": "^2.0.3", - "@types/react": "^18.0.34", + "@types/jest": "^29.5.7", + "@types/react": "^18.2.36", + "@types/react-test-renderer": "^18.0.5", "@typescript-eslint/eslint-plugin": "^5.58.0", "@typescript-eslint/parser": "^5.58.0", "eslint": "^8.38.0", "eslint-plugin-jest": "^27.2.1", + "jest": "^29.7.0", + "metro-react-native-babel-preset": "^0.77.0", "prettier": "^2.8.7", "react": "^18.2.0", "react-native": "^0.71.6", "react-native-builder-bob": "^0.20.4", + "react-test-renderer": "^18.2.0", "release-it": "^15.10.1", "typescript": "^4.9.4" }, diff --git a/test/hooks.test.tsx b/test/hooks.test.tsx new file mode 100644 index 00000000..e24abd16 --- /dev/null +++ b/test/hooks.test.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import { Button, Text } from 'react-native'; +import { + act, + fireEvent, + render, + renderHook, + screen, +} from '@testing-library/react-native'; +import { MMKV, useMMKVNumber, useMMKVString } from '../src'; + +const mmkv = new MMKV(); + +beforeEach(() => { + mmkv.clearAll(); +}); + +test('hooks update when the value is changed directly through the instance', () => { + const { result } = renderHook(() => useMMKVString('string-key', mmkv)); + + expect(result.current[0]).toBeUndefined(); + + // First, make a "normal" change + act(() => { + result.current[1]('value 1'); + }); + + expect(result.current[0]).toStrictEqual('value 1'); + + // Now, make the change directly through the instance. + act(() => { + mmkv.set('string-key', 'value 2'); + }); + expect(result.current[0]).toStrictEqual('value 2'); +}); + +test('functional updates to hooks', () => { + const Component: React.FC = () => { + const [state, setState] = React.useState(0); + const [value, setValue] = useMMKVNumber('number-key', mmkv); + + return ( + <> +