Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dressca-Consumer]フロントエンドの自動テストサンプルを拡充する #1482

Open
KentaHizume opened this issue Oct 30, 2024 · 5 comments · May be fixed by #1939
Open

[Dressca-Consumer]フロントエンドの自動テストサンプルを拡充する #1482

KentaHizume opened this issue Oct 30, 2024 · 5 comments · May be fixed by #1939
Assignees
Labels
target: Dressca サンプルアプリケーションDresscaに関係がある
Milestone

Comments

@KentaHizume
Copy link
Contributor

KentaHizume commented Oct 30, 2024

概要

DressccaのConsumerアプリについて、フロントエンドの自動テストのサンプルを拡充する。

2025/1/24 時点

v 1.0 時点では実装なし。

拡充したい内容

  • VitestでAPIコールをモックした正常系のテスト
  • VitestでAPIコールをモックした異常系のテスト
  • msw を用いた api-client のテスト
    • Vitest ではaxiosのレスポンス自体をモックする関係で api-client 部分はテストできないため、msw のモックで補完する

完了条件

ここにこの Issue の完了条件を箇条書きで記載します。

@KentaHizume
Copy link
Contributor Author

KentaHizume commented Dec 6, 2024

下記のようなテストを実装すると、「カートの取得に失敗しました。」のメッセージをうまく取得できない。

NotificationToastコンポーネントがmountしているBasketViewのtemplateではなくApp.vueのtemplateにいるため。

App.vueをmountしてから買い物かご画面に遷移するようにしなければ確認できなさそう。

describe('異常系', () => {
  beforeAll((): void => {
    getBasketItemsMock.mockRejectedValue(new ServerError('ServerError'));
  });
  it('サーバーエラー', async () => {
    // Arrange
    const pinia = createPinia();
    setActivePinia(pinia);
    const customErrorHandler = createCustomErrorHandler();
    const wrapper = mount(BasketView, {
      global: { plugins: [pinia, router, customErrorHandler] },
    });

    // Act
    await flushPromises();

    // Assert
    expect(wrapper.html()).toContain('カートの取得に失敗しました。');
  });
});

notificationStoreの中身をassetすれば確認はできるが、ユーザー目線のテストとしてはUIをテストしたのであまりよくない。
一方でApp.vueからmountするのはテスト範囲として大きすぎる。

@KentaHizume
Copy link
Contributor Author

巻き上げ

1ファイル内でmockのふるまいを変更する場合は、vi.hoistedを使用する必要がある。
vi.mockを複数回宣言すると、最後に宣言したもので上書きされてしまう。

https://vitest.dev/api/vi#mock-modules
https://dev.classmethod.jp/articles/handling-exception-hoist-in-vitest/

@KentaHizume
Copy link
Contributor Author

異常系

下記のように想定されるErrorを返却することでモックできる。

getBasketItemsMock.mockRejectedValue(new ServerError('ServerError'));

ただし、axiosによるAPIのレスポンスをモックしてしまうので、axiosのinterceptorの挙動(下記の箇所)はVitestのモックではテストできない。

if (error.response.status === 500) {
 return Promise.reject(new ServerError('Server Error', error));
}

@KentaHizume
Copy link
Contributor Author

KentaHizume commented Jan 28, 2025

言語設定(多言語対応)

vue-i18n を導入したところ、
Vitest(jsdom)上ではlocaleがenになってしまい日本語のメッセージの検証に失敗してしまうので、
うまく localeを設定する必要がある。

- 買い物かごに商品がありません。
+ <div class="container mx-auto my-4 max-w-4xl">
+   <!--v-if-->
+   <div>
+     <!--v-if-->
+     <div class="mt-4 mx-2"><span class="text-2xl font-medium">There are no items in the basket.</span></div>

言語設定をjaに変更してからアプリをマウントすると動作する。

  i18n.global.locale.value = 'ja';

下記で書き換えるパターンも出てくるが、うまく動かない(英語になる)
vue-i18n を import したタイミングでen(jsdomのデフォルト値)になってしまうためと思われる。

    Object.defineProperty(window.navigator, "language", {
      value: "ja-JP",
      configurable: true,
    });

@KentaHizume
Copy link
Contributor Author

AxiosError のモック

errorMessageFormatで使用しているので、
AxiosErrorを作ってProblemDetails等の必要な部分を詰めてあげないと想定通りの動きをしない。

    const problem = createProblemDetails({
      exceptionId: 'serverError',
      status: 500,
    });
    const error = createAxiosError(problem);
    getBasketItemsMock.mockRejectedValue(new ServerError('message', error));
function createAxiosError(problemDetails: ProblemDetails): AxiosError {
  const error = new AxiosError('', '', undefined, null, {
    status: problemDetails.status,
    statusText: '',
    headers: {},
    config: {
      headers: new AxiosHeaders({
        'Content-Type': 'application/json',
      }),
    },
    data: {
      detail: problemDetails.detail,
      exceptionId: problemDetails.exceptionId,
      exceptionValues: problemDetails.exceptionValues,
      instance: problemDetails.instance,
      status: problemDetails.status,
      title: problemDetails.title,
      type: problemDetails.type,
    },
  });
  return error;
}

mockモードの動作

mockモードでも特にAxiosErrorを詰めていないので、
ステータスコードをいじって挙動を確認するとvue-i18nがエラーを吐いているので、
本来はAxiosErrorを作って返すようにしたほうがよい。

Image

@tsuna-can-se tsuna-can-se added the target: Dressca サンプルアプリケーションDresscaに関係がある label Jan 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
target: Dressca サンプルアプリケーションDresscaに関係がある
Projects
None yet
2 participants