Async-storage: SyntaxError: Unexpected token export using jest

Created on 14 Mar 2019  ·  37Comments  ·  Source: react-native-async-storage/async-storage

Current behavior

/@react-native-community/async-storage/lib/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export default from './AsyncStorage';

 SyntaxError: Unexpected token export

    > 1 | import AsyncStorage  from "@react-native-community/async-storage"
        | ^
      2 | 
      3 | /**
      4 |  * Loads a string from storage.

Repro steps

import @react-native-community/async-storage and test with jest.

Environment

  • Async Storage version: 1.2.1
  • React-Native version: 0.57.7
  • Platform tested: iOS / Android
  • Jest version: 24.0.11
  • Logs/Error that are relevant: see above
bug

Most helpful comment

Sure @Krizzu! As you said in your comment I've created __mocks__/@react-native-community/async-storage/index.js

let cache = {};
export default {
  setItem: (key, value) => {
    return new Promise((resolve, reject) => {
      return (typeof key !== 'string' || typeof value !== 'string')
        ? reject(new Error('key and value must be string'))
        : resolve(cache[key] = value);
    });
  },
  getItem: (key, value) => {
    return new Promise((resolve) => {
      return cache.hasOwnProperty(key)
        ? resolve(cache[key])
        : resolve(null);
    });
  },
  removeItem: (key) => {
    return new Promise((resolve, reject) => {
      return cache.hasOwnProperty(key)
        ? resolve(delete cache[key])
        : reject('No such key!');
    });
  },
  clear: (key) => {
    return new Promise((resolve, reject) => resolve(cache = {}));
  },

  getAllKeys: (key) => {
    return new Promise((resolve, reject) => resolve(Object.keys(cache)));
  },
}

An then in my tests I just import and mock @react-native-community/async-storage like this:

import AsyncStorage from '@react-native-community/async-storage';
jest.mock('@react-native-community/async-storage');

All 37 comments

Hey @loic-lopez

Async Storage is not being transformed by Jest, so in your jest.config.js or jest entry in package.json, add:

"transformIgnorePatterns": ["/node_modules/@react-native-community/async-storage/(?!(lib))"]

The error still happening after adding your solution.

@Krizzu thanks for reply and yes transformIgnorePatterns seems to have solved the problem but,
when i try to mock the library like that:
Capture d’écran 2019-03-15 à 11 30 54

I got:

● save

    expect(jest.fn()).toHaveBeenCalledWith(expected)

    Expected mock function to have been called with:
      ["something", "{\"x\":1}"]
    But it was not called.

      34 | test("save", async () => {
      35 |   await save("something", VALUE_OBJECT)
    > 36 |   expect(mockSetItem).toHaveBeenCalledWith("something", VALUE_STRING)
         |                       ^
      37 | })
      38 | 
      39 | test("saveString", async () => {

      at Object.<anonymous>.test (test/tests/storage.test.ts:36:23)

as if the mock did not work

@loic-lopez This is more like Jest question :) You can checkout Jest docs about mocking node_modules libs.

Basically, create __mocks__ in project root (unless your roots Jest settings says differently), create @react-native-community/async-storage/index.js in there and export mocked functions.

@vgm8 Anything particular that could help me figuring this out?

@Krizzu the mock is on top of my @react-native-community/async-storage test see bellow:
Capture d’écran 2019-03-15 à 12 08 05

@Krizzu your solution was not working because i had some errors in the jest configuration. After I fixed it works fine, thank you!

@vgm8 Thanks great!

Would you mind sharing your solution, for future references?

@Krizzu As you can see above, the mock is being running before my tests.

I have same issue. @loic-lopez

Sure @Krizzu! As you said in your comment I've created __mocks__/@react-native-community/async-storage/index.js

let cache = {};
export default {
  setItem: (key, value) => {
    return new Promise((resolve, reject) => {
      return (typeof key !== 'string' || typeof value !== 'string')
        ? reject(new Error('key and value must be string'))
        : resolve(cache[key] = value);
    });
  },
  getItem: (key, value) => {
    return new Promise((resolve) => {
      return cache.hasOwnProperty(key)
        ? resolve(cache[key])
        : resolve(null);
    });
  },
  removeItem: (key) => {
    return new Promise((resolve, reject) => {
      return cache.hasOwnProperty(key)
        ? resolve(delete cache[key])
        : reject('No such key!');
    });
  },
  clear: (key) => {
    return new Promise((resolve, reject) => resolve(cache = {}));
  },

  getAllKeys: (key) => {
    return new Promise((resolve, reject) => resolve(Object.keys(cache)));
  },
}

An then in my tests I just import and mock @react-native-community/async-storage like this:

import AsyncStorage from '@react-native-community/async-storage';
jest.mock('@react-native-community/async-storage');

@NemanjaManot Do you have resolved your issue?

@loic-lopez not yet.

getting
@RNCommunity/AsyncStorage: NativeModule.RCTAsyncStorage is null.
after adding transformIgnorePatterns

@opiruyan Thanks!

This is from latest release (1.2.2), where we notice devs to link the library in order to use it.

I'll try to come up with custom mocks + docs to help people test this library on the weekend.

thanks.

@vgm8, thanks for your mock implementation, it saved me time and I can confirm that it works.

Hey everyone participating in this issue,

I've created a PR with mocks and jest integration guide, so I hope future issues with testing would be resolved.

Let me know what you think!

thanks.

edit fixed link

@Krizzu thanks but your link seems to be broken.

@Krizzu

Updated the lib but I din't get the @react-native-community/async-storage/jest/async-storage-mock

The jest folder doesn't seem to be included in the dist of react-native-async-storage?

"dependencies": { "@react-native-community/async-storage": "1.2.4",

@nirre7,

Jest mocking is not yet releases, going to do it after merging #61 and #57 later today.

Oh, I thought it was since it was in the docs.
No worries, thanks for the quick answer though.

looks like RN took care of transformIgnorePatters-part of the issue
https://github.com/facebook/react-native/releases/tag/v0.59.4

Released in v1.3.0, please check it out 🙏

@Krizzu I'm still have issues, are you aware of this problem:

 FAIL  src/slides/AskNotifications/AskNotificationsConnected.tests.js
  ● Test suite failed to run

    .../node_modules/@react-native-community/async-storage/jest/async-storage-mock.js:6
    type KeysType = Array<string>;
         ^^^^^^^^

    SyntaxError: Unexpected identifier

The solution here was switching to a different mocking package but I'm hoping that's not necessary.

@Krizzu I'm still have issues, are you aware of this problem:

 FAIL  src/slides/AskNotifications/AskNotificationsConnected.tests.js
  ● Test suite failed to run

    .../node_modules/@react-native-community/async-storage/jest/async-storage-mock.js:6
    type KeysType = Array<string>;
         ^^^^^^^^

    SyntaxError: Unexpected identifier

The solution here was switching to a different mocking package but I'm hoping that's not necessary.

turns out I fixed it by using @vgm8's mock above So maybe there's a syntax error in your official one that Jest doesn't like.

@Krizzu should the problem mentioned above be fixed in the official mock? I'm getting the same thing.

@redreceipt @janpe We use this setup on the repo's example app and it's fine. Seems like your setup might be missing a proper flow handling.
What's the preset you use? How does your setup look like? Could you come up with a repo that I could look into?

We see the same KeysType error. Also fixable by using @vgm8's mock.

It seems like the issue comes from the lack of transformation by Jest. We have a docs on how to fix this here. Let me know if it worked.

@Krizzu, no help, at least, with the "Jest setup file" option.

So to be clear, I've followed the instructions to include 2 lines in my setup file, AND included the transformIgnorePatterns you suggested.

[EDIT] Ah, right, but I'm also using RN 0.59.10, so since that ignore pattern is already part of 0.59.4, my understanding is that this should be unnecessary.

[EDIT2] I'd swear this has something to do with Typescript not being recognized. Does that help?

[EDIT3] Ok, so FLOW, not TypeScript, and I seem to have determined, "No, it's not a tumor!" (i.e. that's not the problem) BTW, sorry for the constant EDITs -- hopefully this is clearer than replying to myself a million times in separate posts.

[EDIT4] Some progress. So creating __mocks__/@react-native-community/async-storage.js and copying the contents of node_modules/@react-native-community/jest/async-storage-mock.js into there, I get errors related to async/await not being properly transpiled by Babel. So adding @babel/preset-env to my project (npm i -D @babel/preset-env) and including the following in my babel.config.js:

module.exports = {
    presets: [
        [
            '@babel/preset-env',
            { targets: { node: '8' } },
        ],
    ],
};

With this setup, tests pass. But if instead of copying the contents I just have the export default from '@react-native-community/async-storage/jest/async-storage-mock' line from the instructions, I get errors pointing to KeysType again.

As far as I understand things, which at this point is not all that well, this would sure seem to indicate that my node_modules files are, in fact, not being transpiled by Babel before being passed on to Jest.

@frozenzia did you find the solution for this? im having the same...

@cinder92 , no, actually. I got fed up / out-of-time trying to figure out what was going on with the mock included in the package, and just went with a modified version of @vgm8's mock. We only needed setItem, getItem, and removeItem, AND we have some airBnB eslint rules in place so that the end result was that __mocks__/@react-native-community/async-storage.js (note name! opted for this instead of making an additional async-storage folder and putting index.js in it) looks like this:

const cache = {};
export default {
    setItem: (key, value) => new Promise((resolve, reject) => {
        const retVal = (typeof key !== 'string' || typeof value !== 'string')
            ? reject(new Error('key and value must be string'))
            : resolve(cache[key] = value);
        return retVal;
    }),
    getItem: key => new Promise(resolve => (
        Object.prototype.hasOwnProperty.call(cache, key)
            ? resolve(cache[key])
            : resolve(null))),
    removeItem: key => new Promise((resolve, reject) => (
        Object.prototype.hasOwnProperty.call(cache, key)
            ? resolve(delete cache[key])
            : reject(new Error('No such key!')))),
};

@frozenzia How does your setup looks like? Is it monorepo by any chance?

type KeysType = Array<string>;
     ^^^^^^^^
SyntaxError: Unexpected identifier

Looks like an issue with Flow type striping. Do you have it included in your project?

My project neither contains Flow nor TypeScript and I too get the KeysType error:

  ● Test suite failed to runmponent.test.js

    /Users/jan/dev/my-app/node_modules/@react-native-communit
y/async-storage/jest/async-storage-mock.js:
6
    type KeysType = Array<string>;
         ^^^^^^^^

    SyntaxError: Unexpected identifier

It feels like @react-native-community/async-storage/jest/async-storage-mock needs to be fixed to work with plain JS projects.

It's also possible to exclude this file in .flowconfig by adding <PROJECT_ROOT>/node_modules/@react-native-community/async-storage/jest/.* under the [ignore] section

I have fixed the error

type KeysType = Array<string>;
         ^^^^^^^^

    SyntaxError: Unexpected identifier

using those instructions in my project: https://github.com/react-native-community/async-storage/blob/LEGACY/docs/Jest-integration.md#syntaxerror-unexpected-token-export-in-async-storagelibindexjs

I have fixed the error

type KeysType = Array<string>;
         ^^^^^^^^

    SyntaxError: Unexpected identifier

using those instructions in my project: https://github.com/react-native-community/async-storage/blob/LEGACY/docs/Jest-integration.md#syntaxerror-unexpected-token-export-in-async-storagelibindexjs

https://github.com/react-native-community/async-storage/issues/194#issuecomment-562094202

Was this page helpful?
0 / 5 - 0 ratings