aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.4k stars 2.11k forks source link

Jest test fails because of incorrectly loaded react native modules #13167

Open itsramiel opened 3 months ago

itsramiel commented 3 months ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

DataStore

Amplify Version

v6

Amplify Categories

Not applicable

Backend

None

Environment information

``` # Put output below this line System: OS: macOS 14.3.1 CPU: (14) arm64 Apple M3 Max Memory: 142.31 MB / 36.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node Yarn: 1.22.21 - ~/.nvm/versions/node/v20.11.1/bin/yarn npm: 10.2.4 - ~/.nvm/versions/node/v20.11.1/bin/npm Watchman: 2024.01.22.00 - /opt/homebrew/bin/watchman Browsers: Chrome: 123.0.6312.58 Safari: 17.3.1 npmPackages: @aws-amplify/react-native: ^1.0.22 => 1.0.22 @azure/core-asynciterator-polyfill: ^1.0.2 => 1.0.2 @babel/core: ^7.20.0 => 7.24.3 @babel/preset-env: ^7.20.0 => 7.24.3 @babel/runtime: ^7.20.0 => 7.24.1 @react-native-async-storage/async-storage: ^1.23.1 => 1.23.1 @react-native-community/netinfo: ^11.3.1 => 11.3.1 @react-native/babel-preset: 0.73.21 => 0.73.21 @react-native/eslint-config: 0.73.2 => 0.73.2 @react-native/metro-config: 0.73.5 => 0.73.5 @react-native/typescript-config: 0.73.1 => 0.73.1 @types/react: ^18.2.6 => 18.2.69 @types/react-test-renderer: ^18.0.0 => 18.0.7 HelloWorld: 0.0.1 aws-amplify: ^6.0.21 => 6.0.21 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/data: undefined () aws-amplify/data/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () babel-jest: ^29.6.3 => 29.7.0 eslint: ^8.19.0 => 8.57.0 jest: ^29.6.3 => 29.7.0 prettier: 2.8.8 => 2.8.8 react: 18.2.0 => 18.2.0 react-native: 0.73.6 => 0.73.6 react-native-get-random-values: ^1.11.0 => 1.11.0 react-test-renderer: 18.2.0 => 18.2.0 typescript: 5.0.4 => 5.0.4 npmGlobalPackages: @aws-amplify/cli: 12.3.0 corepack: 0.23.0 eas-cli: 7.3.0 npm: 10.2.4 yarn: 1.22.21 ```

Describe the bug

When testing a react native app with jest, I get the following error message: Ensure@react-native-async-storage/async-storageis installed and linked.

with the source being at loadAsyncStorage (node_modules/@aws-amplify/react-native/src/moduleLoaders/loadAsyncStorage.ts:22:15)

The issue is that when loading the module, the module is loaded with require().default: https://github.com/aws-amplify/amplify-js/blob/2b71e29d50204f037b1dae2007291c54d1ec8c19/packages/react-native/src/moduleLoaders/loadAsyncStorage.ts#L10-L11

But the mock that is shipped with react-native-async-storage/async-storage is a common js object with no default property, so require('@react-native-async-storage/async-storage')?.default is always undefind in jest, but require('@react-native-async-storage/async-storage') is defined

Expected behavior

I expect to not get the error Ensure@react-native-async-storage/async-storageis installed and linked. since it is installed and mocked properly according to the library docs.

Reproduction steps

  1. clone https://github.com/itsramiel/AmplifyJestRepro
  2. Install deps with yarn
  3. Run yarn test and check the error

Code Snippet

// Put your code below this line.

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

itsramiel commented 3 months ago

Is there any reason why const module = require('@react-native-async-storage/async-storage')?.default as AsyncStorageStatic; is not imported as an esm import import AsyncStorage from 'react-native-async-storage/async-storage' and then assigning AsyncStorage to module?

ashwinkumar6 commented 1 month ago

Hi @itsramiel, Thanks for raising the issue, this is a duplicate of #12829 Could you try adding a mock as mentioned on the linked issue

cwomack commented 3 weeks ago

@itsramiel, wanted to follow up and see if you had a chance to try adding a mock as mentioned in the issue referenced in @ashwinkumar6's comment. Let us know if you're still having this issue and if we can help, thanks!

itsramiel commented 3 weeks ago

Yeah I already use the following mock:

jest.mock('@aws-amplify/react-native', () => {
  const original = jest.requireActual('@aws-amplify/react-native');
  return {
    ...original,
    loadAsyncStorage: jest.fn(),
    loadNetInfo: jest.fn(() => ({
      addEventListener: jest.fn(),
    })),
  };
});

but I was wondering if there is a plan to handle that internally