あなたの固体をテストします.JSTコード



だから、あなたは良いアプリや図書館での書き込みを開始しているSolid.js とタイプスクリプト-良い選択-しかし、今では何も壊れないことを確認するすべてのユニットをテストします.

Jest 現在、フロントエンドテストのための最良のオプションの一つですが、それは固体とうまく再生するいくつかのセットアップが必要です.jsつのオプションがあります.
  • solid-jest - バベルを使用してセットアップを設定するためのプリセットを設定します.チェックをタイプしませんが、より速いです
  • ts-jest - JESTを使用したモジュールを使用して、強制的にビットを強制する必要があります.js
  • を使用している場合はsolid-jest タイプチェックを欠く費用でテストを実行するときに時間を節約できますが、これらは別々に実行できます.ts-jest あなたのためのタイプをチェックするが、少し長くなります.どちらの選択肢も有効ですので、自分で決めてください.

    構成
    ソリッドJestまたはTs Jestを使用している場合は、ソリッドをサポートするBabel Configが必要になります.JS -主な違いはどこに置くことです.次のようになります.
    {
      "presets": [
        "@babel/preset-env",
        "babel-preset-solid",
        // only if you use TS with solid-jest
        "@babel/preset-typescript"
      ]
    }
    
    実行するには、dev依存関係を追加する必要があります@babel/core , @babel/preset-env オプション@babel/preset-typescript TypeScriptを使用するかどうかによって異なります.
    あなたが使用することを決めたならばsolid-jest , 次に、Babelの設定を.babelrc プロジェクトルートのファイル;それ以外の場合は、パッケージ内のjest設定セクションに入ります.来たるべきJSON/冗談ts-jest セクション.

    しっかりした
    For solid-jest , 必要なjest設定.babelrc このようなコメントを実行するには、
    {
      "jest" : {
        "preset": "solid-jest/preset/browser",
        // insert setupFiles and other config
      }
    }
    

    TSジェスト
    あなたが使うならばts-jest 代わりに、このように見えます(コメントなし).
    { 
      "jest": {
        "preset": "ts-jest",
        "globals": {
          "ts-jest": {
            "tsconfig": "tsconfig.json",
            "babelConfig": {
              "presets": [
                "babel-preset-solid",
                "@babel/preset-env"
              ]
            }
          }
        },
        // insert setupFiles and other config
        // you probably want to test in browser mode:
        "testEnvironment": "jsdom",
        // unfortunately, solid cannot detect browser mode here,
        // so we need to manually point it to the right versions:
        "moduleNameMapper": {
          "solid-js/web": "<rootDir>/node_modules/solid-js/web/dist/web.cjs",
          "solid-js": "<rootDir>/node_modules/solid-js/dist/solid.cjs"
        }
      }
    }
    

    今何?
    私は、あなたがすでに冗談のまわりであなたの方法を知っていると思います.そうでなければ、私はあなたにこれを指摘させてください.では、なぜここに多くのテキストですか?いくつかのより多くの考慮点は、固体のテストです.JSコード:
  • 効果とメモは、反応根の中で働くだけです
  • コンポーネントは、要素を出力します.
  • つまり、実際のレンダリングのすべての代わりにいくつかのショートカットを使用することができますし、DOMの視点からそれを見ています.使用可能なショートカットを見てみましょう.

    カスタムプリミティブのテスト(フック)
    機能を再利用可能にする強力な方法は、別の原始関数にそれを置くことです.「lorem ipsum」テキストの変数の数を返す関数のナイーブ実装を行いましょう.
    const loremIpsumWords = 'Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'.split(/\s+/);
    
    const createLorem = (words: Accessor<number> | number) => {
      return createMemo(() => {
        const output = [],
          len = typeof words === 'function' ? words() : words;
        while (output.length <= len) {
          output.push(...loremIpsumWords);
        }
    
        return output.slice(0, len).join(' ');
      });
    };
    
    我々が使うならばwords アクセサーとして、それは反応性のルートの中で更新されるだけです、そして、アップデートは効果の中で利用できるだけです.幸いにも、JestはAsync関数を喜んで待ちますので、最終的に評価される出力を収集するための約束を使用できます.
    test(
      'it updates the result when words update',
      async () => {
        const input = [3, 2, 5],
          expectedOutput = [
            'Lorem ipsum dolor',
            'Lorem ipsum',
            'Lorem ipsum dolor sit amet'
          ];
    
        const actualOutput = await new Promise<string[]>(resolve => createRoot(dispose => {
          const [words, setWords] = createSignal(input.shift() ?? 3);
          const lorem = createLorem(words);
    
          const output: string[] = [];
          createEffect(() => {
            // effects are batched, so the escape condition needs
            // to run after the output is complete:
            if (input.length === 0) {
              dispose();
              resolve(output);
            }
            output.push(lorem());
            setWords(input.shift() ?? 0);
          });
        }));
    
        expect(actualOutput).toEqual(expectedOutput);
      }
    );
    
    この方法では、出力をレンダリングする必要もなく、テストケースで非常に柔軟です.

    テストディレクティブuse:... )
    エーcustom directive が存在する場合、DOM参照と引数を持つアクセッサを受け取るプリミティブです.フルスクリーンAPIを説明するディレクティブを考えましょう.次の署名があります.
    export type FullscreenDirective = (
      ref: HTMLElement,
      active: Accessor<boolean | FullscreenOptions>
    ) => void;
    
    のように使われます:
    const [fs, setFs] = createSignal(false);
    return <div use:FullscreenDirective={fs}>...</div>;
    
    現在、指令をテストするために、我々は提出する必要がありますか?いいえ、我々はありません!使用してhtmlelementを作成することができますdocument.createElement('div') そして、我々の前の原始のようにテストしてください.
    ユーザーの視点から物事をテストしたいと主張することができますが、ディレクティブのユーザーは、まだコンポーネントで使用する開発者です-そして、あなたは固体の場合にテストする必要はありません.JSは実際には動作しています.
    実際の例を見ることができますfullscreen primitive from solid-primitives 本当にあなたによって書かれます.

    コンポーネントのテスト
    最後に、レンダリングを使用する!違う?返されたDOM要素をテストしているとは言わないでください.
    よく、あなたは確かにそれをすることができました、しかし、コンポーネントが通常、DOM文脈で使用されているので、コンポーネントのコンテキストだけではなく、レンダリングが副作用を導入することができるので、私はあなたがそうするべきではないと示唆しています.代わりに、私はあなたを指すようにしたいSolid's testing library .
    では、追加しましょうsolid-testing-library 我々のプロジェクトに@testing-library/jest-dom 設定します.
    // in package.json
    {
      // ...
      "jest": {
        "preset": "solid-jest/preset/browser",
        "setupFilesAfterEnv": ["./src/setupTests.ts"]
      }
    }
    
    // and in ./src/setupTests.ts:
    import "regenerator-runtime/runtime";
    import '@testing-library/jest-dom'
    
    このプロジェクトには、以下のような無意味なコンポーネントが含まれています.
    import { createSignal, Component, JSX } from 'solid-js';
    
    export const MyComponent: Component<JSX.HTMLAttributes<HTMLDivElement>> = (props) => {
      const [clicked, setClicked] = createSignal(false);
      return <div {...props} role="button" onClick={() => setClicked(true)}>
        {clicked() ? 'Test this!' : 'Click me!'}
      </div>;
    };
    
    では、テストライブラリを使って簡単なテストを書きましょう.
    import { screen, render, fireEvent } from 'solid-testing-library';
    import { MyComponent } from './my-component';
    
    test('changes text on click', async () => {
      await render(() => <MyComponent />);
      const component = await screen.findByRole('button', { name: 'Click me!' });
      expect(component).toBeInTheDocument();
      fireEvent.click(component);
      expect(await screen.findByRole('button', { name: 'Test this!' })).toBeInTheDocument();
    });
    
    これを実行しましょう.
    > jest
    
     PASS  src/testing.test.tsx
      ✓ changes text on click (53 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        4.012 s
    Ran all test suites.
    
    あなたのテストは、すべてのバグをキャッチ!