Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BrowserWindow mock type #817

Closed
Tanimodori opened this issue Jul 27, 2022 · 2 comments · Fixed by #818
Closed

BrowserWindow mock type #817

Tanimodori opened this issue Jul 27, 2022 · 2 comments · Fixed by #818
Assignees
Labels
bug Something isn't working

Comments

@Tanimodori
Copy link
Contributor

Tanimodori commented Jul 27, 2022

Describe the bug

The types of Mock of BrowserWindow use vitest internal type MaybeMocked

import type {MaybeMocked} from 'vitest';
import {beforeEach, expect, test, vi} from 'vitest';
import {restoreOrCreateWindow} from '../src/mainWindow';
import {BrowserWindow} from 'electron';
/**
* Mock real electron BrowserWindow API
*/
vi.mock('electron', () => {
const bw = vi.fn() as MaybeMocked<typeof BrowserWindow>;
// @ts-expect-error It's work in runtime, but I Haven't idea how to fix this type error
bw.getAllWindows = vi.fn(() => bw.mock.instances);
bw.prototype.loadURL = vi.fn();
bw.prototype.on = vi.fn();
bw.prototype.destroy = vi.fn();
bw.prototype.isDestroyed = vi.fn();
bw.prototype.isMinimized = vi.fn();
bw.prototype.focus = vi.fn();
bw.prototype.restore = vi.fn();
return {BrowserWindow: bw};
});

Fix

Use MockedObject will fix this issue but the type of bw.prototype is any.

import type {MockedObject} from 'vitest';
import {beforeEach, expect, test, vi} from 'vitest';
import {restoreOrCreateWindow} from '../src/mainWindow';

import {BrowserWindow} from 'electron';

/**
 * Mock real electron BrowserWindow API
 */
vi.mock('electron', () => {

  const bw = vi.fn() as MockedObject<typeof BrowserWindow>;
  bw.getAllWindows = vi.fn(() => bw.mock.instances);
  // bw.prototype is any
  bw.prototype.loadURL = vi.fn();
  bw.prototype.on = vi.fn();
  bw.prototype.destroy = vi.fn();
  bw.prototype.isDestroyed = vi.fn();
  bw.prototype.isMinimized = vi.fn();
  bw.prototype.focus = vi.fn();
  bw.prototype.restore = vi.fn();

  return {BrowserWindow: bw};
});

For the strictest typing, use MockedClass which ports the prototype part of BrowerWindow class. Unfortunately there's a bug of MockedClass type in vistest (see vitest-dev/vitest#1730 , basically they put args and returns in wrong positions lol). I have to include a manual fix for that.

import type {Constructable, Mocked, MockInstance} from 'vitest';
import {beforeEach, expect, test, vi} from 'vitest';
import {restoreOrCreateWindow} from '../src/mainWindow';

import {BrowserWindow} from 'electron';

// Manual fix of MockedClass type
// See https://github.com/vitest-dev/vitest/issues/1730
type MockedClass<T extends Constructable> = MockInstance<T extends new (...args: infer P) => any ? P : never, InstanceType<T>> & {
  prototype: T extends {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      prototype: any;
  } ? Mocked<T['prototype']> : never;
} & T;

/**
 * Mock real electron BrowserWindow API
 */
vi.mock('electron', () => {

  // Use "as unknown as" because vi.fn() does not have static methods
  const bw = vi.fn() as unknown as MockedClass<typeof BrowserWindow>;
  bw.getAllWindows = vi.fn(() => bw.mock.instances);
  bw.prototype.loadURL = vi.fn();
  // Use "any" because the on function is overloaded
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  bw.prototype.on = vi.fn<any>();
  bw.prototype.destroy = vi.fn();
  bw.prototype.isDestroyed = vi.fn();
  bw.prototype.isMinimized = vi.fn();
  bw.prototype.focus = vi.fn();
  bw.prototype.restore = vi.fn();

  return {BrowserWindow: bw};
});

All the fix does not change the runtime behaviors, just types.

@Tanimodori Tanimodori added the bug Something isn't working label Jul 27, 2022
@cawa-93
Copy link
Owner

cawa-93 commented Jul 27, 2022

LGTM. May you make pr?

@Tanimodori
Copy link
Contributor Author

The MockedClass issue is fixed in vitest-dev/vitest#1735 . Expected to remove the temp fix once the dep version is dumped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants