ホームページ >ウェブフロントエンド >jsチュートリアル >シリアライザーを使用してスナップショットから動的値を削除する方法

シリアライザーを使用してスナップショットから動的値を削除する方法

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-30 13:50:10945ブラウズ

How To Remove Dynamic Values From Snapshot With Serializers

Jest および Vitest のスナップショット テストは、コードの出力における予期しない変更を検出するための強力なツールです。ただし、テストの実行ごとに変化する生成された ID やタイムスタンプなどの動的な値を扱う場合、簡単に壊れてしまいます。これらの値をモックすることは可能ですが、意図しない副作用が生じる可能性があります。

API 呼び出しまたはデータベース クエリから返される可能性がある次のユーザー オブジェクトについて考えてみましょう。

const user = {
  id: crypto.randomUUID(),
  name: "John Doe",
  createdAt: new Date().toISOString()
};

テストを実行するたびに、id と createdAt の値が異なるため、スナップショットが失敗します。

基本的な実装

動的値を一貫したプレースホルダーに置き換えるカスタム シリアライザーを作成する方法は次のとおりです。

const property = 'id';
const placeholder = '[ID]';

expect.addSnapshotSerializer({
  test(val) {
    return val && typeof val === 'object' && Object.hasOwn(val, property) && val[property] !== placeholder
  },
  serialize(val, config, indentation, depth, refs, printer) {
    return printer(
      {
        ...(val as Record<string, unknown>),
        [property]: placeholder,
      },
      config,
      indentation,
      depth,
      refs,
    );
  },
});

expect.addSnapshotSerializer() を使用してカスタム スナップショット シリアライザーを追加できます。
2 つの関数を持つオブジェクトが必要です:

  • test() は、このカスタム シリアライザーを使用するかどうかを決定するために使用されます。 Expect(value) の値がプロパティを持つオブジェクトであり、プレースホルダーによって置き換えられていないかをチェックします。

  • serialize() は、test() が true を返した場合にのみ呼び出されます。プロパティをプレースホルダーに置き換え、printer() 関数を呼び出して値を JSON のような文字列にシリアル化します。

テスト

これで、テストを実行すると、ID が [ID] プレースホルダーに置き換えられたことがわかります。

interface User {
  id: string;
  name: string;
  createdAt: string;
}

expect.addSnapshotSerializer({ /* ... */ });

test('snapshot', () => {
  const user: User = {
    id: '123e4567-e89b-12d3-a456-426614174000',
    name: 'John Doe',
    createdAt: '2024-03-20T12:00:00Z',
  };

  expect(user).toMatchInlineSnapshot(`
    {
      "id": "[ID]",
      "name": "John Doe",
    }
  `);
});

再利用可能にする

複数の動的プロパティを処理する必要がある場合はどうすればよいでしょうか?再利用可能なソリューションを作成しましょう:

export const replaceProperty = (
  property: string,
  placeholder: string,
): SnapshotSerializer => {
  return {
    test(val) {
      return val && typeof val === 'object' && Object.hasOwn(val, property) && val[property] !== placeholder
    },
    serialize(val, config, indentation, depth, refs, printer) {
      return printer(
        {
          ...(val as Record<string, unknown>),
          [property]: placeholder,
        },
        config,
        indentation,
        depth,
        refs,
      );
    },
  };
};

テストでは、さまざまなプロパティに対して複数のシリアライザーを作成できます。

expect.addSnapshotSerializer(replaceProperty('id', '[ID]'));
expect.addSnapshotSerializer(replaceProperty('createdAt', '[TIMESTAMP]'));

私はこれらのシリアライザーを頻繁に使用するため、誰でも簡単に使えるように npm パッケージ snapshot-serializers を作成しました。

import { replaceProperty, removeProperty } from 'snapshot-serializers';

type User = {
  id: string;
  name: string;
  createdAt: string;
  password?: string;
};

// Type-safe property replacement
expect.addSnapshotSerializer(
  // TypeScript will only allow "id" | "name" | "createdAt" | "password"
  replaceProperty<User>({
    property: 'id',
    placeholder: '[ID]'
  })
);

// Remove properties entirely
expect.addSnapshotSerializer(
  removeProperty<User>({
    property: 'password'
  })
);

// This would cause a TypeScript error:
expect.addSnapshotSerializer(
  replaceProperty<User>({
    property: 'invalid' // Error: Type '"invalid"' is not assignable...
  })
);

スナップショット内のプロパティを置換または削除するためのタイプセーフ API を提供します。 RemoveProperty() のようなジェネリック型パラメータを指定すると、関数は User 型に基づいて考えられるすべてのプロパティ名を提案します。他のプロパティを使用すると TypeScript エラーが発生します。

以上がシリアライザーを使用してスナップショットから動的値を削除する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:API 統合について次の記事:API 統合について