🔧

HydrogenのHello Worldテンプレートにe2eテストを追加する

2022/11/03に公開約5,000字

以下まで実施した状態のHello Worldテンプレートにe2eテストを追加する。
https://shopify.dev/custom-storefronts/hydrogen/getting-started/tutorial/fetch-data

実行環境

  • Mac
  • Node.js v18.12.0

必要なパッケージのインストール

DemoStoreのテンプレートを参考に、テストに必要なパッケージをインストールする。

npm i --save-dev vitest playwright

https://shopify.dev/custom-storefronts/hydrogen/best-practices/testing

テスト実行用のnpmスクリプトを追加する

こちらもDemoStoreのpackage.jsonを参考に、テスト実行用のスクリプト(testtest:ci)を追加する。

package.json
{
  "name": "hydrogen-app",
  ~~
  "scripts": {
    "dev": "shopify hydrogen dev",
    "build": "shopify hydrogen build",
    "preview": "shopify hydrogen preview",
    "test": "WATCH=true vitest",
    "test:ci": "yarn build -t node && vitest run"
  },
  ~~
}

テストファイルを追加する

DemoStoreのテストを参考に、tests/配下に以下のファイルを作成する。

  • utils.ts(DemoStoreと同じなので詳細は割愛)
  • e2e/index.test.ts
e2e/index.test.ts
import {
  startHydrogenServer,
  type HydrogenServer,
  type HydrogenSession,
} from '../utils';
import Index from '../../src/routes/index.server';
import { describe, beforeAll, beforeEach, afterAll, it, expect } from 'vitest';

describe('index', () => {
  let hydrogen: HydrogenServer;
  let session: HydrogenSession;

  beforeAll(async () => {
    hydrogen = await startHydrogenServer();
    hydrogen.watchForUpdates(Index);
  });

  beforeEach(async () => {
    session = await hydrogen.newPage();
  });

  afterAll(async () => {
    await hydrogen.cleanUp();
  });

  it('should be a 200 response', async () => {
    const response = await session.visit('/');
    expect(response!.status()).toBe(200);
  });
});

tests/e2e/index.test.tsには1つのテストが含まれているが、localhostにアクセスして200が返ってくるか確認しているだけなのでほとんど意味はない。

テストを実施する

npm run test

テストを1回実行し、watch状態になる。
watch状態になると、テストファイルに変更があるたびにテストを実行してくれるため、テストを開発したいときに便利。
スクリプトの中身はWATCH=true vitestとなっており、WATCH=trueでは環境変数WATCHtrueをセット(utils.ts内で使用)、vitestでテストをwatchモードで起動している。
vitestはデフォルトでwatchモードでテスト実行するが、vitest runとすると1回だけ実行することができる。また、vitest run --coverageとすることでカバレッジを出力することも可能。

https://vitest.dev/guide/

$ npm run test
 ❯ tests/e2e/index.test.ts (1)
   ❯ index (1)
stdout | tests/e2e/index.test.ts > index > should be a 200 response
GET streaming SSR     200 ok    1333.24 ms http://localhost:56708/

 ✓ tests/e2e/index.test.ts (1) 4156ms

Test Files  1 passed (1)
     Tests  1 passed (1)
  Start at  16:26:14
  Duration  6.57s (transform 1.38s, setup 0ms, collect 1.59s, tests 4.16s)


 PASS  Waiting for file changes...
       press h to show help, press q to quit

テストが成功していることが確認できたら、「q」を押してwatchモードを終了する。

npm run test:ci

ビルドを行った後に、テストを1回だけ実行する。
スクリプトの中身はyarn build -t node && vitest runとなっており、Node.js用にビルドを行ったあと、vitest runでテストを1回だけ実行している。

 ❯ tests/e2e/index.test.ts (1)
   ❯ index (1)
stderr | tests/e2e/index.test.ts > index > should be a 200 response
Error: undefined No secret Shopify storefront API token was defined. This means your app will be rate limited!
See how to add the token: 

stdout | tests/e2e/index.test.ts > index > should be a 200 response
GET streaming SSR     200 ok    786.51 ms  http://localhost:56763/

stderr | tests/e2e/index.test.ts > index > should be a 200 response
WARN:  No session adapter has been configured!

 ✓ tests/e2e/index.test.ts (1) 1562ms

Test Files  1 passed (1)
     Tests  1 passed (1)
  Start at  16:32:32
  Duration  4.33s (transform 1.37s, setup 0ms, collect 1.67s, tests 1.56s)

テストを追加する

上記のテストだけでは味気ないので、「GraphQLで取得した店名が画面を表示した際に表示されているか」、というテストを追加する。

まず、店名を表示するComponentを探しやすくするためid=shop-nameを付与する。

src/components/Layout.server.tsx
~~
          <div className="flex gap-12">
            <Link id="shop-name" className="font-bold" to="/">
              {shop.name}
            </Link>
          </div>
~~

次に、テストファイル(tests/e2e/index.test.ts)にテストを追加する。

tests/e2e/index.test.ts
  it('should show the shop name', async () => {
    await session.visit('/');
    const heading = await session.page.locator('#shop-name').first();
    expect(await heading.textContent()).equal(SHOP_NAME);
  });

最後にテストを実行する。

❯ tests/e2e/index.test.ts (2)
   ❯ index (2)
stderr | tests/e2e/index.test.ts > index > should be a 200 response
Error: undefined No secret Shopify storefront API token was defined. This means your app will be rate limited!
See how to add the token: 

stdout | tests/e2e/index.test.ts > index > should be a 200 response
GET streaming SSR     200 ok    561.20 ms  http://localhost:65151/

stderr | tests/e2e/index.test.ts > index > should be a 200 response
WARN:  No session adapter has been configured!

 ✓ tests/e2e/index.test.ts (2) 1542ms

Test Files  1 passed (1)
     Tests  2 passed (2)
  Start at  17:46:07
  Duration  4.44s (transform 1.44s, setup 0ms, collect 1.76s, tests 1.54s)

Discussion

ログインするとコメントできます