tkzwhr's notes

tkzwhrの技術、中国語などのメモです。

Create React Appで作成したプロジェクトをJestでテストしようとするとGraphQLのファイルが読み込めない

モックサーバーとして建てたGraphQLサーバーを利用して useQuery を使ったカスタムフックのテストしようと思い、 GraphQLの変換処理を設定してテストを起動したところ、エラーになってしまった。

package.json

{
  ...,
  "jest": {
    "transform": {
      "\\.(graphql|gql)$": "jest-transform-graphql"
    },
  }
}
$ npm run test

... (中略)

Invariant Violation: Argument of foobar.graphql passed to parser was not a valid GraphQL DocumentNode. You may need to use 'graphql-tag' or another method to convert your operation into a document

ファイルのインポートはできているようだが、インポートされた内容が DocumentNode ではなくファイル名の文字列( foobar.graphql )になってしまっている。

react-app-rewired を使ってJestにどのような設定が渡されているか確認したところ、下記の通りだった。

config-overrides.js

module.exports = {
  jest: function override(config) {
    console.log(config);
    process.abort();
    return config;
  }
};
$ npm run test
{
  ...,
  transform: {
    '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': '/path/to/project/node_modules/react-app-rewired/scripts/utils/babelTransform.js',
    '^.+\\.css$': '/path/to/project/node_modules/react-scripts/config/jest/cssTransform.js',
    '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': '/path/to/project/node_modules/react-scripts/config/jest/fileTransform.js',
    '\\.(graphql|gql)$': 'jest-transform-graphql'
  },
  ...
}

これを見ると、 .graphql ファイルが transform の3行目にある fileTransform.js のファイルパターンに合致してしまっているため、 jest-transform-graphql に到達できていないことがわかった。

この transform は react-scripts 内に定義されている。

github.com

対策の方法が分からなかったので、 react-app-rewiredfileTransform.js の例外パターンを追加することにした。

const FILE_TRANSFER_KEY = "js|jsx|mjs|cjs|ts|tsx|css|json";
module.exports = {
  jest: function override(config) {
    Object.keys(config.transform).forEach(key => {
      const replacedKey = key.replace(FILE_TRANSFER_KEY, `${FILE_TRANSFER_KEY}|graphql|gql`);
      if (key !== replacedKey) {
        config.transform[replacedKey] = config.transform[key];
        delete config.transform[key];
      }
    });
    return config;
  }
};

これで .graphql ファイルが正常にロードされるようになった。