jest で Blob をモックにしてテストしたかったのですが、Node.js に Blob は定義されていませんでした。
未定義なので定義することで対応してみました。
作成したコード
まずはテスト対象のコードです。前回のコードを typescript で別ファイルにしました。
export default function downloadText(fileName: string, text: string) {
const blob = new Blob([text], { type: 'text/plain' });
const aTag = document.createElement('a');
aTag.href = URL.createObjectURL(blob);
aTag.target = '_blank';
aTag.download = fileName;
aTag.click();
URL.revokeObjectURL(aTag.href);
}
そして、テストコードは以下です。
ここでは意図した値で Blob を作成したか?を確認し、Aタグについては割愛しています。
import downloadText from './downloadText';
class BlobMock {
constructor(
content: Array<ArrayBuffer | ArrayBufferView | Blob | String> | undefined,
options: BlobPropertyBag | undefined,
) {
this.content = content;
this.options = options;
}
public content: Array<ArrayBuffer | ArrayBufferView | Blob | String> | undefined;
public options: BlobPropertyBag | undefined;
}
test('downloadText', () => {
(global as any).Blob = BlobMock;
const backup1 = window.URL.createObjectURL;
const backup2 = window.URL.revokeObjectURL;
window.URL.createObjectURL = jest.fn();
window.URL.revokeObjectURL = jest.fn();
downloadText('sample.txt', '一富士二鷹三茄子');
expect(window.URL.createObjectURL).toBeCalledWith({
content: ['一富士二鷹三茄子'],
options: { type: 'text/plain' },
});
window.URL.createObjectURL = backup1;
window.URL.revokeObjectURL = backup2;
});
悩んだポイント1:どう Blob を定義するか
未定義だからといって、
global.Blob = BlobMock;
にすると、“A file-like object of immutable, raw data. Blobs represent data that isn’t necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user’s system.” と言われてしまうので、
(global as any).Blob = BlobMock;
の通り、global を一旦 any にして Blob を設定しています。
悩んだポイント2:URL.createObjectURL をモックにできない
モックにできないというか、
jest.spyOn(window.URL, 'createObjectURL').mockImplementation(jest.fn());
だと、
Cannot spy the createObjectURL property because it is not a function; undefined given instead
となってしまうので、関数を定義することで乗り越えました。
コメント