Linaria を入れたら Jest、Testing Library が動かなくなったのを解決する

2021/01/10 00:57
話題になっている Linaria
自分のサイトでも入れようと思い、インストールしました。ところが、導入まではうまくいったものの、Jest(Testing Library を使ってます)が通らなくなりました。なんでやねん。
alt
Using the "styled" tag in runtime is not supported....などというエラーが出ました。調べてみるとどうも根が深そう。
調査を進めていくうちに下記の投稿を発見(こういう調査は毎回骨が折れる)
要約すると…
・Linaria の関数をmock化する
・mock化した関数からタグ名を返してもらう
という理解です。そうすることで、Jest を実行した時に Linaria で指定したタグ名が返ってくるので、これを Testing Library がタグとして認識します。
タグとして認識できれば、どのような要素なのかが判別でき、Role なども判別できますね。

コード例

早速実装事例を記載します。

テストしたいコンポーネント

これは実際に当ブログで使われている Footer の Component です。単純にコピーライトと名前が入っています。
import React from 'react';

import { StyledFooter } from './styledFooter'; // Linaria が使われてる CSS in JS を分割したもの

const Footer: React.FC = () => {
  return <StyledFooter>© 2021 HOSONOKOTARO Tech Blog</StyledFooter>;
};

export default Footer;

テスト

期待したい結果として、Role が contentinfo のものの中に、指定したテキストが存在するか?というものです。必要な処理は通常のテストコードに加えて mock 関数が挟まってます(詳しくは後述)
import '@testing-library/jest-dom/extend-expect';

import { render, screen } from '@testing-library/react';
import React from 'react';

import Footer from './Footer';

jest.mock('@linaria/react', () => {
  const styled = (tag: string | number | symbol) => {
    return jest.fn(() => tag.toString());
  };

  return {
    styled: new Proxy(styled, {
      get(o, prop) {
        return o(prop);
      },
    }),
  };
});

it('it should render: Footer', () => {
  render(<Footer />);
  expect(screen.getByRole('contentinfo')).toHaveTextContent(
    '© 2021 HOSONOKOTARO Tech Blog'
  );
});

解説

テストコードの中にあるjest.mock()で Linaria のライブラリを Wrap します。これでstyled.divなどの処理が mock 化されます。
その際にタグ名を取得したいので関数内にnew Proxy()を記載し、入ってくるタグ名を傍受します。
これでタグ名が取得できるのでjest.fn()でタグ名を return します。すると、次のようにタグ名が正しく取得できます。
alt
footer の Role は contentinfo なので、それも正しく認識していますね。あとはテストしていくだけ。