PostHog / posthog-js-lite

Reimplementation of posthog-js to be as light and modular as possible.
https://posthog.com/docs/libraries
MIT License
70 stars 36 forks source link

React Native app tested with jest fails with: PostHog: No storage available. Please install expo-filesystem or react-native-async-storage OR implement a custom storage provider. #143

Closed itsramiel closed 11 months ago

itsramiel commented 11 months ago

Bug description

When trying to test a react native app with PostHog installed, the following error is thrown: Error: PostHog: No storage available. Please install expo-filesystem or react-native-async-storage OR implement a custom storage provider. at buildOptimisiticAsyncStorage even though async storage is installed

How to reproduce

  1. create a new react native project with npx react-native@latest init AwesomeProject as mentioned in the docs
  2. Install with yarn add posthog-react-native @react-native-async-storage/async-storage react-native-device-info and configure posthog
  3. run yarn test -> Fails

Related sub-libraries

Additional context

Thank you for your bug report – we love squashing them!

benjackwhite commented 11 months ago

To me it sounds like the error describes what needs to be done quite clearly 😅

What exactly is the bug?

itsramiel commented 11 months ago

Installation was done with yarn add posthog-react-native @react-native-async-storage/async-storage react-native-device-info, so async storage is there.

It works fine when running on a device or simulator, but not in jest.

How is that not a bug?

itsramiel commented 11 months ago

@benjackwhite were you able to reproduce that?

marandaneto commented 11 months ago

@itsramiel did you check that your libs are also available for the devDependencies target? Try to run the very same command (yarn add...) with the --dev argument, which then installs the libs as devDependencies.

itsramiel commented 11 months ago

Hi @marandaneto. Yes that also doesnt work.

Here is a repro with 4 branches installing as dep/devDep and mocking async storage vs not:

image

Please let me know the issue. Or feel free to create a repo that successfully passes yarn test initialized with a new react native project for me to check out

marandaneto commented 11 months ago

The problem is that those libraries don't support macOS/Linux/Windows, just the Android/iOS targets mostly. So trying to load them via tests won't work.

You can do that (mocking) in many ways:

By setting a customAsyncStorage mock, or persistence: 'memory' during testing.

export const myStorageMock = (): PostHogCustomAsyncStorage => {
  return {
    async getItem(key: string) {
      return null
    },

    async setItem(key: string, value: string) {

    },
  }
}

PostHog.initAsync('<ph_project_api_key>', {
  host: 'https://app.posthog.com',
  // persistence: 'memory',
  // or a customAsyncStorage mock
  // customAsyncStorage: myStorageMock(),
}).then(client => {
  posthog = client;
});

Or even mocking the library directly as explained here https://react-native-async-storage.github.io/async-storage/docs/advanced/jest/

We cannot do those mocks in the SDK directly so your tests won't fail, the best we can do is to not throw if the deps are not available, Maybe the SDK should not throw in this case, but just console log and fallback to persistence: 'memory' in this case? WDYT @benjackwhite ?

itsramiel commented 11 months ago

Setting the persistence to be in-memory while testing sounds like a good idea.

Btw I was already mocking the storage library as provided by the repo I linked above. This contains a mock for async storage, but for some reason require(...).default returns undefined but if that was was changed to import xxx from '....' it works fine even in testing. But I am assuming require is used to be in a conditional.

Anyways I'll try the in-memory option for now