私のアプリケーションには、(かなり不十分に書かれた)javascriptコンポーネントがあり、無限スクロールのページ付けを処理します。記述されているように、IntersectionObserver
を使用するように書き直そうとしています here ただし、私はテストに問題があります。
QUnitテストでオブザーバーの動作を制御する方法はありますか。つまり、テストに記述されているいくつかのエントリでオブザーバーコールバックをトリガーする方法はありますか?
私が思いついた考えられる解決策は、コンポーネントのプロトタイプでコールバック関数を公開し、次のように、テストで直接呼び出すことです。
InfiniteScroll.prototype.observerCallback = function(entries) {
//handle the infinite scroll
}
InfiniteScroll.prototype.initObserver = function() {
var io = new IntersectionObserver(this.observerCallback);
io.observe(someElements);
}
//In my test
var component = new InfiniteScroll();
component.observerCallback(someEntries);
//Do some assertions about the state after the callback has been executed
コンポーネントがIntersectionObserver
を内部で使用するという事実を公開しているため、このアプローチはあまり好きではありません。これは、実装の詳細であり、クライアントのコードからは見えないはずなので、より良い方法があります。これをテストしますか?
JQueryを使用しないソリューションへのボーナス愛:)
これは、以前の回答に基づく別の代替方法です。beforeEach
メソッド内、または_.test.js
_ファイルの先頭で実行できます。
パラメータをsetupIntersectionObserverMock
に渡してobserve
および/またはunobserve
メソッドをモックしてjest.fn()
モック関数でスパイすることもできます。
_/**
* Utility function that mocks the `IntersectionObserver` API. Necessary for components that rely
* on it, otherwise the tests will crash. Recommended to execute inside `beforeEach`.
* @param {object} intersectionObserverMock - Parameter that is sent to the `Object.defineProperty`
* overwrite method. `jest.fn()` mock functions can be passed here if the goal is to not only
* mock the intersection observer, but its methods.
*/
export function setupIntersectionObserverMock({
observe = () => null,
unobserve = () => null,
} = {}) {
class IntersectionObserver {
observe = observe;
unobserve = unobserve;
}
Object.defineProperty(
window,
'IntersectionObserver',
{ writable: true, configurable: true, value: IntersectionObserver }
);
Object.defineProperty(
global,
'IntersectionObserver',
{ writable: true, configurable: true, value: IntersectionObserver }
);
}
_
2019年の同じ問題はこれが私がそれを解決した方法です:
import ....
describe('IntersectionObserverMokTest', () => {
...
const observeMock = {
observe: () => null,
disconnect: () => null // maybe not needed
};
beforeEach(async(() => {
(<any> window).IntersectionObserver = () => observeMock;
....
}));
if(' should run the Test without throwing an error for the IntersectionObserver', () => {
...
})
});
そこで、observe
(およびdisconnect
)メソッドを使用してモックオブジェクトを作成し、ウィンドウオブジェクトのIntersectionObserver
を上書きします。使用方法によっては、他の関数を上書きする必要がある場合があります(以下を参照してください: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Browser_compatibility )
コードは https://Gist.github.com/ianmcnally/4b68c56900a20840b6ca840e2403771c から着想を得ていますが、jest
を使用していません
jest.setup.jsファイルで、IntersectionObserverを次の実装でモックします。
global.IntersectionObserver = class IntersectionObserver {
constructor() {}
observe() {
return null;
}
unobserve() {
return null;
}
};
Jest Setup File を使用する代わりに、テストまたはbeforeAll、beforeEachブロックで直接このモッキングを行うこともできます。