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

2021/01/10 00:57
話題になっている Linaria
自分のサイトでも入れようと思い、インストールしました。ところが、導入まではうまくいったものの、Jest(Testing Library を使ってます)が通らなくなりました。なんでやねん。
alt
Using the "styled" tag in runtime is not supported....などというエラーが出ました。調べてみるとどうも根が深そう。
調査を進めていくうちに下記の投稿を発見(こういう調査は毎回骨が折れる)
要約すると…

という理解です。そうすることで、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 なので、それも正しく認識していますね。あとはテストしていくだけ。