首頁 >web前端 >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()新增自訂快照序列化器。
它需要一個具有兩個功能的物件:

  • 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 套件快照序列化器來讓每個人都更容易使用。

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(),該函數將根據使用者類型建議所有可能的屬性名稱。任何其他屬性都會導致 TypeScript 錯誤。

以上是如何使用序列化器從快照中刪除動態值的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:了解 API 集成下一篇:了解 API 集成