モッキング
このサービスは、Vitestのようなインターフェースを介して、Electron API機能のモッキングを可能にします。
ブラウザユーティリティメソッド
mock
API名と関数名が提供された場合、Electron API機能をモックします。モックオブジェクトが返されます。
例:スペックファイル内
const mockedShowOpenDialog = await browser.electron.mock('dialog', 'showOpenDialog');
await browser.electron.execute(
async (electron) =>
await electron.dialog.showOpenDialog({
properties: ['openFile', 'openDirectory'],
}),
);
expect(mockedShowOpenDialog).toHaveBeenCalledTimes(1);
expect(mockedShowOpenDialog).toHaveBeenCalledWith({
properties: ['openFile', 'openDirectory'],
});
mockAll
Electron APIのすべての関数を同時にモックします。モックはオブジェクトとして返されます。
const { showOpenDialog, showMessageBox } = await browser.electron.mockAll('dialog');
await showOpenDialog.mockReturnValue('I opened a dialog!');
await showMessageBox.mockReturnValue('I opened a message box!');
clearAllMocks
アクティブな各モックに対してmockClear
を呼び出します。
const mockSetName = await browser.electron.mock('app', 'setName');
const mockWriteText = await browser.electron.mock('clipboard', 'writeText');
await browser.electron.execute((electron) => electron.app.setName('new app name'));
await browser.electron.execute((electron) => electron.clipboard.writeText('text to be written'));
await browser.electron.clearAllMocks();
expect(mockSetName.mock.calls).toStrictEqual([]);
expect(mockWriteText.mock.calls).toStrictEqual([]);
apiName文字列を渡すと、その特定のAPIのモックがクリアされます。
const mockSetName = await browser.electron.mock('app', 'setName');
const mockWriteText = await browser.electron.mock('clipboard', 'writeText');
await browser.electron.execute((electron) => electron.app.setName('new app name'));
await browser.electron.execute((electron) => electron.clipboard.writeText('text to be written'));
await browser.electron.clearAllMocks('app');
expect(mockSetName.mock.calls).toStrictEqual([]);
expect(mockWriteText.mock.calls).toStrictEqual([['text to be written']]);
resetAllMocks
アクティブな各モックに対してmockReset
を呼び出します。
const mockGetName = await browser.electron.mock('app', 'getName');
const mockReadText = await browser.electron.mock('clipboard', 'readText');
await mockGetName.mockReturnValue('mocked appName');
await mockReadText.mockReturnValue('mocked clipboardText');
await browser.electron.resetAllMocks();
const appName = await browser.electron.execute((electron) => electron.app.getName());
const clipboardText = await browser.electron.execute((electron) => electron.clipboard.readText());
expect(appName).toBeUndefined();
expect(clipboardText).toBeUndefined();
apiName文字列を渡すと、その特定のAPIのモックがリセットされます。
const mockGetName = await browser.electron.mock('app', 'getName');
const mockReadText = await browser.electron.mock('clipboard', 'readText');
await mockGetName.mockReturnValue('mocked appName');
await mockReadText.mockReturnValue('mocked clipboardText');
await browser.electron.resetAllMocks('app');
const appName = await browser.electron.execute((electron) => electron.app.getName());
const clipboardText = await browser.electron.execute((electron) => electron.clipboard.readText());
expect(appName).toBeUndefined();
expect(clipboardText).toBe('mocked clipboardText');
restoreAllMocks
アクティブな各モックに対してmockRestore
を呼び出します。
const mockGetName = await browser.electron.mock('app', 'getName');
const mockReadText = await browser.electron.mock('clipboard', 'readText');
await mockGetName.mockReturnValue('mocked appName');
await mockReadText.mockReturnValue('mocked clipboardText');
await browser.electron.restoreAllMocks();
const appName = await browser.electron.execute((electron) => electron.app.getName());
const clipboardText = await browser.electron.execute((electron) => electron.clipboard.readText());
expect(appName).toBe('my real app name');
expect(clipboardText).toBe('some real clipboard text');
apiName文字列を渡すと、その特定のAPIのモックが復元されます。
const mockGetName = await browser.electron.mock('app', 'getName');
const mockReadText = await browser.electron.mock('clipboard', 'readText');
await mockGetName.mockReturnValue('mocked appName');
await mockReadText.mockReturnValue('mocked clipboardText');
await browser.electron.restoreAllMocks('app');
const appName = await browser.electron.execute((electron) => electron.app.getName());
const clipboardText = await browser.electron.execute((electron) => electron.clipboard.readText());
expect(appName).toBe('my real app name');
expect(clipboardText).toBe('mocked clipboardText');
isMockFunction
指定されたパラメータがElectronモック関数であることを確認します。TypeScriptを使用している場合、その型も絞り込まれます。
const mockGetName = await browser.electron.mock('app', 'getName');
expect(browser.electron.isMockFunction(mockGetName)).toBe(true);
モックオブジェクト
各モックオブジェクトには、次のメソッドが使用可能です。
mockImplementation
モックの実装として使用される関数を受け入れます。
const mockGetName = await browser.electron.mock('app', 'getName');
let callsCount = 0;
await mockGetName.mockImplementation(() => {
// callsCount is not accessible in the electron context so we need to guard it
if (typeof callsCount !== 'undefined') {
callsCount++;
}
return 'mocked value';
});
const result = await browser.electron.execute(async (electron) => await electron.app.getName());
expect(callsCount).toBe(1);
expect(result).toBe('mocked value');
mockImplementationOnce
次の呼び出し中にモックの実装として使用される関数を受け入れます。チェーンされている場合、連続する呼び出しごとに異なる結果が生成されます。
モック関数の実装がなくなると、mockImplementation
で設定されたデフォルトの実装が呼び出されます。
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockImplementationOnce(() => 'first mock');
await mockGetName.mockImplementationOnce(() => 'second mock');
let name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBe('first mock');
name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBe('second mock');
name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBeNull();
mockReturnValue
モック関数が呼び出されるたびに返される値を受け入れます。
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockReturnValue('mocked name');
const name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBe('mocked name');
mockReturnValueOnce
次の関数呼び出し中に返される値を受け入れます。チェーンされている場合、連続する呼び出しごとに指定された値が返されます。
使用するmockReturnValueOnce
値がなくなると、モックは以前に定義された実装にフォールバックします(存在する場合)。
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockReturnValueOnce('first mock');
await mockGetName.mockReturnValueOnce('second mock');
let name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBe('first mock');
name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBe('second mock');
name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBeNull();
mockResolvedValue
モック関数が呼び出されるたびに解決される値を受け入れます。
const mockGetFileIcon = await browser.electron.mock('app', 'getFileIcon');
await mockGetFileIcon.mockResolvedValue('This is a mock');
const fileIcon = await browser.electron.execute(async (electron) => await electron.app.getFileIcon('/path/to/icon'));
expect(fileIcon).toBe('This is a mock');
mockResolvedValueOnce
次の関数呼び出し中に解決される値を受け入れます。チェーンされている場合、連続する呼び出しごとに指定された値が解決されます。
使用するmockResolvedValueOnce
値がなくなると、モックは以前に定義された実装にフォールバックします(存在する場合)。
const mockGetFileIcon = await browser.electron.mock('app', 'getFileIcon');
await mockGetFileIcon.mockResolvedValue('default mocked icon');
await mockGetFileIcon.mockResolvedValueOnce('first mocked icon');
await mockGetFileIcon.mockResolvedValueOnce('second mocked icon');
let fileIcon = await browser.electron.execute(async (electron) => await electron.app.getFileIcon('/path/to/icon'));
expect(fileIcon).toBe('first mocked icon');
fileIcon = await browser.electron.execute(async (electron) => await electron.app.getFileIcon('/path/to/icon'));
expect(fileIcon).toBe('second mocked icon');
fileIcon = await browser.electron.execute(async (electron) => await electron.app.getFileIcon('/path/to/icon'));
expect(fileIcon).toBe('default mocked icon');
mockRejectedValue
モック関数が呼び出されるたびに拒否される値を受け入れます。
const mockGetFileIcon = await browser.electron.mock('app', 'getFileIcon');
await mockGetFileIcon.mockRejectedValue('This is a mock error');
const fileIconError = await browser.electron.execute(async (electron) => {
try {
await electron.app.getFileIcon('/path/to/icon');
} catch (e) {
return e;
}
});
expect(fileIconError).toBe('This is a mock error');
mockRejectedValueOnce
次の関数呼び出し中に拒否される値を受け入れます。チェーンされている場合、連続する呼び出しごとに指定された値が拒否されます。
使用するmockRejectedValueOnce
値がなくなると、モックは以前に定義された実装にフォールバックします(存在する場合)。
const mockGetFileIcon = await browser.electron.mock('app', 'getFileIcon');
await mockGetFileIcon.mockRejectedValue('default mocked icon error');
await mockGetFileIcon.mockRejectedValueOnce('first mocked icon error');
await mockGetFileIcon.mockRejectedValueOnce('second mocked icon error');
const getFileIcon = async () =>
await browser.electron.execute(async (electron) => {
try {
await electron.app.getFileIcon('/path/to/icon');
} catch (e) {
return e;
}
});
let fileIcon = await getFileIcon();
expect(fileIcon).toBe('first mocked icon error');
fileIcon = await getFileIcon();
expect(fileIcon).toBe('second mocked icon error');
fileIcon = await getFileIcon();
expect(fileIcon).toBe('default mocked icon error');
mockClear
モックされたElectron API関数の履歴をクリアします。モック実装はリセットされません。
const mockGetName = await browser.electron.mock('app', 'getName');
await browser.electron.execute((electron) => electron.app.getName());
await mockGetName.mockClear();
await browser.electron.execute((electron) => electron.app.getName());
expect(mockGetName).toHaveBeenCalledTimes(1);
mockReset
モックされたElectron API関数をリセットします。モック履歴はクリアされ、実装は空の関数(undefinedを返す)にリセットされます。
これは、すべての「一度だけ」実装もリセットします。
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockReturnValue('mocked name');
await browser.electron.execute((electron) => electron.app.getName());
await mockGetName.mockReset();
const name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBeUndefined();
expect(mockGetName).toHaveBeenCalledTimes(1);
mockRestore
Electron API関数に元の実装を復元します。
const appName = await browser.electron.execute((electron) => electron.app.getName());
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockReturnValue('mocked name');
await mockGetName.mockRestore();
const name = await browser.electron.execute((electron) => electron.app.getName());
expect(name).toBe(appName);
withImplementation
コールバックが実行されている間、元のモック実装を一時的にオーバーライドします。electronオブジェクトは、execute
の場合と同様にコールバックに渡されます。
const mockGetName = await browser.electron.mock('app', 'getName');
const withImplementationResult = await mockGetName.withImplementation(
() => 'temporary mock name',
(electron) => electron.app.getName(),
);
expect(withImplementationResult).toBe('temporary mock name');
非同期コールバックでも使用できます。
const mockGetFileIcon = await browser.electron.mock('app', 'getFileIcon');
const withImplementationResult = await mockGetFileIcon.withImplementation(
() => Promise.resolve('temporary mock icon'),
async (electron) => await electron.app.getFileIcon('/path/to/icon'),
);
expect(withImplementationResult).toBe('temporary mock icon');
getMockImplementation
現在のモック実装がある場合は、それを返します。
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockImplementation(() => 'mocked name');
const mockImpl = mockGetName.getMockImplementation();
expect(mockImpl()).toBe('mocked name');
getMockName
モックの割り当てられた名前を返します。デフォルトは`electron.<apiName>.<funcName>`です。
const mockGetName = await browser.electron.mock('app', 'getName');
expect(mockGetName.getMockName()).toBe('electron.app.getName');
mockName
モックに名前を割り当てます。名前はgetMockName
を介して取得できます。
const mockGetName = await browser.electron.mock('app', 'getName');
mockGetName.mockName('test mock');
expect(mockGetName.getMockName()).toBe('test mock');
mockReturnThis
実装を呼び出さずにメソッドから`this`コンテキストを返す必要がある場合に便利です。これは次の省略形です。
await spy.mockImplementation(function () {
return this;
});
...これにより、API関数をチェーンできます。
const mockGetName = await browser.electron.mock('app', 'getName');
const mockGetVersion = await browser.electron.mock('app', 'getVersion');
await mockGetName.mockReturnThis();
await browser.electron.execute((electron) => electron.app.getName().getVersion());
expect(mockGetVersion).toHaveBeenCalled();
mock.calls
これは、各呼び出しのすべての引数を格納する配列です。配列の各項目は、その呼び出しの引数です。
const mockGetFileIcon = await browser.electron.mock('app', 'getFileIcon');
await browser.electron.execute((electron) => electron.app.getFileIcon('/path/to/icon'));
await browser.electron.execute((electron) => electron.app.getFileIcon('/path/to/another/icon', { size: 'small' }));
expect(mockGetFileIcon.mock.calls).toStrictEqual([
['/path/to/icon'], // first call
['/path/to/another/icon', { size: 'small' }], // second call
]);
mock.lastCall
これは、最後の呼び出しの引数を格納します。モックが呼び出されなかった場合、`undefined`を返します。
const mockSetName = await browser.electron.mock('app', 'setName');
await browser.electron.execute((electron) => electron.app.setName('test'));
expect(mockSetName.mock.lastCall).toStrictEqual(['test']);
await browser.electron.execute((electron) => electron.app.setName('test 2'));
expect(mockSetName.mock.lastCall).toStrictEqual(['test 2']);
await browser.electron.execute((electron) => electron.app.setName('test 3'));
expect(mockSetName.mock.lastCall).toStrictEqual(['test 3']);
mock.results
これは、モックから返されたすべての値を格納する配列です。配列の各項目は、typeとvalueのプロパティを持つオブジェクトです。使用可能なタイプは次のとおりです。
'return' - モックはスローせずに返されました。 'throw' - モックは値をスローしました。
valueプロパティには、返された値またはスローされたエラーが含まれます。モックがpromiseを返した場合、値は解決された値であり、Promise自体ではありません(解決されなかった場合を除く)。
const mockGetName = await browser.electron.mock('app', 'getName');
await mockGetName.mockImplementationOnce(() => 'result');
await mockGetName.mockImplementation(() => {
throw new Error('thrown error');
});
await expect(browser.electron.execute((electron) => electron.app.getName())).resolves.toBe('result');
await expect(browser.electron.execute((electron) => electron.app.getName())).rejects.toThrow('thrown error');
expect(mockGetName.mock.results).toStrictEqual([
{
type: 'return',
value: 'result',
},
{
type: 'throw',
value: new Error('thrown error'),
},
]);
mock.invocationCallOrder
モック呼び出しの順序。これは、定義されたすべてのモック間で共有される数値の配列を返します。モックが呼び出されなかった場合は、空の配列を返します。
const mockGetName = await browser.electron.mock('app', 'getName');
const mockGetVersion = await browser.electron.mock('app', 'getVersion');
await browser.electron.execute((electron) => electron.app.getName());
await browser.electron.execute((electron) => electron.app.getVersion());
await browser.electron.execute((electron) => electron.app.getName());
expect(mockGetName.mock.invocationCallOrder).toStrictEqual([1, 3]);
expect(mockGetVersion.mock.invocationCallOrder).toStrictEqual([2]);