rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.94k stars 866 forks source link

Strange error returned when running jest [react-native] #1235

Closed Clumsy-Coder closed 4 years ago

Clumsy-Coder commented 4 years ago

Problem

When running jest tests, a strange error is returned.

<path to project>/node_modules/redux-persist/lib/createPersistoid.js:98
    writePromise = storage.setItem(storageKey, serialize(stagedState)).catch(onWriteFail);
                                                                      ^

TypeError: Cannot read property 'catch' of undefined
    at writeStagedState (<path to project>/node_modules/redux-persist/lib/createPersistoid.js:98:71)
    at Timeout.processNextKey [as _onTimeout] (<path to project>/node_modules/redux-persist/lib/createPersistoid.js:87:7)
    at listOnTimeout (internal/timers.js:549:17)
    at processTimers (internal/timers.js:492:7)

Debug info

package.json

{
  "name": "",
  "version": "1.0.6",
  "private": true,
  "scripts": {
    "start": "react-native start",
    "test": "jest",
    "lint": "tsc --build tsconfig.json . && eslint -c .eslintrc.js .",
    "lint:eslint": "eslint -c .eslintrc.js .",
    "lint:tsc": "tsc --build tsconfig.json .",
    "prettier:write": "npx prettier --write **/*.{js,jsx,ts,tsx,json} && npx prettier --write *.{js,jsx,ts,tsx,json}",
    "ios": "react-native run-ios",
    "android:clean": "cd ./android && ./gradlew clean && cd ..",
    "android:debug": "react-native run-android --variant debug",
    "android:release": "react-native run-android --variant release",
    "build:android:all": "cd ./android && ./gradlew assemble && cd ..",
    "build:android:debug": "cd ./android && ./gradlew assembleDebug && cd ..",
    "build:android:release": "cd ./android && ./gradlew assembleRelease && cd ..",
    "fastlane:android:all": "cd ./android && bundle exec fastlane assemble_build && cd ..",
    "fastlane:android:debug": "cd ./android && bundle exec fastlane assemble_debug_build && cd ..",
    "fastlane:android:release": "cd ./android && bundle exec fastlane assemble_release_build && cd .."
  },
  "dependencies": {
    "@react-native-community/async-storage": "^1.11.0",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/native": "^5.7.3",
    "@react-navigation/stack": "^5.9.0",
    "axios": "^0.19.2",
    "build-url": "^2.0.0",
    "lodash": "^4.17.19",
    "native-base": "^2.13.13",
    "re-reselect": "^4.0.0",
    "react": "16.13.1",
    "react-native": "0.63.2",
    "react-native-autocomplete-input": "^4.2.0",
    "react-native-dotenv": "^0.2.0",
    "react-native-gesture-handler": "^1.7.0",
    "react-native-reanimated": "^1.10.1",
    "react-native-safe-area-context": "^3.1.1",
    "react-native-screens": "^2.10.1",
    "react-native-svg": "^12.1.0",
    "react-native-vector-icons": "^7.0.0",
    "react-redux": "^7.2.1",
    "redux": "^4.0.5",
    "redux-persist": "^6.0.0",
    "redux-saga": "^1.1.3",
    "reselect": "^4.0.0",
    "victory-native": "^35.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/runtime": "^7.11.2",
    "@google/semantic-release-replace-plugin": "^1.0.0",
    "@microsoft/tsdoc": "^0.12.20",
    "@react-native-community/eslint-config": "^2.0.0",
    "@semantic-release/changelog": "^5.0.1",
    "@semantic-release/commit-analyzer": "^8.0.1",
    "@semantic-release/git": "^9.0.0",
    "@semantic-release/github": "^7.0.7",
    "@semantic-release/release-notes-generator": "^9.0.1",
    "@testing-library/react-native": "^7.0.1",
    "@types/enzyme": "^3.10.5",
    "@types/enzyme-adapter-react-16": "^1.0.6",
    "@types/faker": "^4.1.12",
    "@types/jest": "^26.0.8",
    "@types/lodash": "^4.14.158",
    "@types/react": "^16.9.44",
    "@types/react-native": "^0.63.4",
    "@types/react-native-autocomplete-input": "^4.0.1",
    "@types/react-native-dotenv": "^0.2.0",
    "@types/react-redux": "^7.1.9",
    "@types/react-test-renderer": "^16.9.3",
    "@types/redux-logger": "^3.0.8",
    "@types/redux-mock-store": "^1.0.2",
    "@types/sinon": "^9.0.4",
    "@typescript-eslint/eslint-plugin": "^3.8.0",
    "@typescript-eslint/parser": "^3.8.0",
    "babel-jest": "^26.2.2",
    "babel-plugin-module-resolver": "^4.0.0",
    "commitizen": "^4.1.2",
    "conventional-changelog-conventionalcommits": "^4.3.0",
    "cz-conventional-changelog": "3.2.0",
    "enzyme": "^3.11.0",
    "enzyme-adapter-react-16": "^1.15.2",
    "enzyme-to-json": "^3.5.0",
    "eslint": "^7.6.0",
    "eslint-config-airbnb-typescript": "^9.0.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-import-resolver-babel-module": "^5.1.2",
    "eslint-plugin-import": "^2.22.0",
    "eslint-plugin-jest": "^23.20.0",
    "eslint-plugin-jsx-a11y": "^6.3.1",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-react": "^7.20.5",
    "eslint-plugin-redux-saga": "^1.1.3",
    "eslint-plugin-tsdoc": "^0.2.6",
    "faker": "^4.1.0",
    "husky": "^4.2.5",
    "jest": "^26.2.2",
    "jest-html-reporters": "^2.0.2",
    "jest-junit": "^11.1.0",
    "lint-staged": "^10.2.11",
    "metro-react-native-babel-preset": "^0.61.0",
    "path": "^0.12.7",
    "prettier": "^2.0.5",
    "pretty-quick": "^2.0.1",
    "react-addons-test-utils": "^15.6.2",
    "react-dom": "^16.13.1",
    "react-native-keyboard-aware-scroll-view": "^0.9.2",
    "react-redux-typescript-scripts": "^1.6.2",
    "react-test-renderer": "^16.13.1",
    "redux-devtools-extension": "^2.13.8",
    "redux-logger": "^3.0.6",
    "redux-mock-store": "^1.5.4",
    "redux-saga-test-plan": "^4.0.0-rc.3",
    "remote-redux-devtools": "^0.5.16",
    "semantic-release": "^17.1.1",
    "sinon": "^9.0.2",
    "ts-jest": "^26.1.4",
    "typescript": "^3.9.7"
  },
  "jest": {
    "preset": "react-native"
  },
  "husky": {
    "hooks": {
      "pre-commit": "pretty-quick --staged && tsc --build tsconfig.json && lint-staged",
      "pre-push": "jest"
    }
  },
  "lint-staged": {
    "*.{js,ts,tsx}": [
      "eslint -c .eslintrc.js"
    ]
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

jest.config.js

module.exports = {
  preset: 'react-native',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  verbose: false,
  collectCoverage: false,
  collectCoverageFrom: [
    '**/*.{js,jsx, ts, tsx}',
    './src/**',
    '!**/node_modules/**',
    '!**/android/**',
    '!**/ios/**',
    '!**/.vscode/**',
    '!**/.circleci/**',
    '!metro.config.js',
    '!babel.config.js',
    '!jest.config.js',
    '!./test-results/**',
    '!./src/configs/**',
    '!./src/**/**/tests/**/*.test.ts.snap',
    '!./src/**/**/tests/**/*.test.ts?.snap',
    '!./coverage/**',
    '!.eslintrc.js',
    '!.prettierrc.js',
    '!index.js',
  ],
  // coverageDirectory: './test-results/coverage/',
  coverageReporters: ['text', 'text-summary', 'lcov', 'clover', 'json'],
  reporters: [
    'default',
    // [
    //   'jest-html-reporter',
    //   {
    //     pageTitle: 'Test Report',
    //     outputPath: './test-results/test-reports.html',
    //     includeFailureMsg: true,
    //     theme: 'darkTheme',
    //   },
    // ],
    [
      'jest-html-reporters',
      {
        publicPath: './test-results/',
        filename: 'test-report.html',
        expand: true,
      },
    ],
    [
      'jest-junit',
      {
        outputDirectory: './test-results/junit',
      },
    ],
  ],
  transform: {
    '^.+\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
    '\\.(ts|tsx)$': 'ts-jest',
  },
  globals: {
    'ts-jest': {
      tsConfig: 'tsconfig.jest.json',
      babelConfig: true,
    },
  },
  setupFiles: ['./jest.setup.js', './node_modules/react-native-gesture-handler/jestSetup.js'],
  transformIgnorePatterns: [
    // eslint-disable-next-line max-len
    'node_modules/(?!(jest-)?react-native|@?react-navigation|native-base|native-base-[a-z, -]*|victory-*|react-native-vector-icons)',
  ],
  snapshotSerializers: ['enzyme-to-json/serializer'],
};

jest.setup.js

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import mockAsyncStorage from '@react-native-community/async-storage/jest/async-storage-mock';

Enzyme.configure({ adapter: new Adapter() });

// eslint-disable-next-line global-require
jest.mock('react-native-reanimated', () => require('react-native-reanimated/mock'));
jest.mock('@react-native-community/async-storage', () => mockAsyncStorage);
jest.mock('@react-navigation/native', () => ({
  ...jest.requireActual('@react-navigation/native'),
  useNavigation: () => ({
    navigate: jest.fn(),
  }),
}));
joonmanji commented 4 years ago

i have the same versions of rn, async-storage and redux-persist as you and i get the error when trying to upgrade to jest version 26.2.2 from 25.5.1

joonmanji commented 4 years ago

mocking createPersistoid in a setup file has worked for me

jest.mock("redux-persist/lib/createPersistoid", () =>
    jest.fn(() => ({
        update: jest.fn(),
        flush: jest.fn(),
    }))
);
Clumsy-Coder commented 4 years ago

@frankenthumbs the solution works. thanks

I created a PR that contains the solution in README.md

https://github.com/rt2zz/redux-persist/pull/1239