jestjs - Typescript'te window.addEventListener türü nasıl yeniden tanımlanır?
Test amaçları için, window.addEventListener'ı taklit etmem gerekiyor (jest ile boş bir mock sadece gözetlemek için yeterlidir). Bunu şu şekilde yapıyorum:
window.addEventListener = jest.fn();
window.removeEventListener = jest.fn();
Sorun şu ki, window.addEventListener.mockClear() yaptığımda, TypeScript bu metodun var olmadığını belirtiyor.
Bununla başa çıkmanın en iyi yolu nedir?
Geçici çözüm: Şu anda bunu yapıyorum ama bunu sürekli yapmak istemiyorum
(window.addEventListener as jest.Mock<{}>).mockClear();
(window.addEventListener as jest.Mock<{}>).mockClear();
Cevap #1
Mevcut arayüzü, o arayüzde ilan edilen metodlara bazı özellikler eklemek için yükseltmenin mümkün olduğunu düşünmüyorum.
Ama bu yöntemlerin üzerine yazabilirsiniz. Tür dönüşümlerini sürekli yazmaktan kaçınmanın bir yolu vardır: ihtiyacınız olduğu şekilde türlenmiş addEventListener ve removeEventListener sahip kendi MockWindow arayüzünüzü tanımlayabilirsiniz. Sonra gerçek window nesnesini bir kez MockWindow olarak dönüştürebilir ve sonrasında bunu kullanabilirsiniz:
interface MockWindow extends Window {
addEventListener: jest.Mock<{}> & typeof window.addEventListener;
removeEventListener: jest.Mock<{}> & typeof window.removeEventListener;
}
function mockWindow() {
window.addEventListener = jest.fn();
window.removeEventListener = jest.fn();
return window as MockWindow;
}
let w = mockWindow();
w.addEventListener('load',function() {});
w.addEventListener.mockClear();
Aslında, mevcut jest tip tanımlarında, jest.Mock arayüzü zaten çok gevşek bir çağrı imzasına sahip olduğu için
interface Mock<T> extends Function {
...
(...args: any[]): any;
jest.Mock olarak beyan edilen herhangi bir şey, herhangi sayıda herhangi parametre ile çağrılabilir ve addEventListener türüne & typeof window.addEventListener eklemeyi gereksiz kılar.
GÜNCELLEME: Görünüşe göre TypeScript yeterince ifade gücüne sahip, bu yüzden genel ve tip kontrolü yapılmış bir fonksiyon yazabilirsiniz:
function mockMethods<T, MethodName extends keyof T>(o: T, methodNames:MethodName[])
: T & {[K in MethodName]: T[K] & jest.Mock<{}>} {
methodNames.forEach(k => {
o[k] = jest.fn() as any;
});
return o as any; // typescript doesn't allow this cast:
// as (T & {[K in MethodKeys]: T[K] & jest.Mock<{}>});
}
let w = mockMethods(window, ['addEventListener', 'removeEventListener']);
w.addEventListener('load', function() {});
w.addEventListener.mockClear();
// you can still call other window methods
w.alert('x');
// and their types are unaffected
w.alert.mockClear(); // error: Property 'mockClear' does not exist
// on type '(message?: any) => void'.
// and you can't mock non-existent methods
let u = mockMethods(window, ['z']); // error: Argument of type '"z"[]'
// is not assignable to parameter of type '("blur" | ...
