mirror of
https://github.com/igorski/bitmappery.git
synced 2026-07-28 01:37:41 +02:00
182 lines
5.3 KiB
TypeScript
182 lines
5.3 KiB
TypeScript
import { vi } from "vitest";
|
|
import { type Store } from "vuex";
|
|
import type { Shape, Selection } from "@/definitions/document";
|
|
import { STORAGE_TYPES } from "@/definitions/storage-types";
|
|
import type ZoomableCanvas from "@/rendering/actors/zoomable-canvas";
|
|
import { type BitMapperyState } from "@/store";
|
|
import { createCanvasState } from "@/store/modules/canvas-module";
|
|
import { createDocumentState } from "@/store/modules/document-module";
|
|
import { createHistoryState } from "@/store/modules/history-module";
|
|
import { createImageState } from "@/store/modules/image-module";
|
|
import { createPreferencesState } from "@/store/modules/preferences-module";
|
|
import { createToolState } from "@/store/modules/tool-module";
|
|
|
|
// zCanvas mocks
|
|
// @todo should not be necessary when updating to zCanvas 6+
|
|
|
|
export function sprite() {
|
|
this._bounds = { left: 0, top: 0, width: 10, height: 10 };
|
|
this._interactive = false;
|
|
this.getBounds = vi.fn().mockReturnValue( this._bounds );
|
|
this.setBounds = vi.fn(( x, y, w, h ) => {
|
|
this._bounds.left = x;
|
|
this._bounds.top = y;
|
|
this._bounds.width = w;
|
|
this._bounds.height = h;
|
|
});
|
|
this.setDraggable = vi.fn();
|
|
this.getInteractive = vi.fn(() => this._interactive );
|
|
this.setInteractive = vi.fn( value => this._interactive = value );
|
|
this.getX = vi.fn();
|
|
this.setX = vi.fn();
|
|
this.getY = vi.fn();
|
|
this.setY = vi.fn();
|
|
this.invalidate = vi.fn();
|
|
this.dispose = vi.fn();
|
|
}
|
|
|
|
export function mockZCanvas() {
|
|
vi.mock( "zcanvas", () => ({
|
|
loader: vi.fn(),
|
|
canvas: vi.fn(),
|
|
sprite,
|
|
}));
|
|
}
|
|
|
|
export function createMockZoomableCanvas(): ZoomableCanvas {
|
|
return {
|
|
width: 300,
|
|
height: 200,
|
|
fps: 60,
|
|
addChild: vi.fn(),
|
|
removeChild: vi.fn(),
|
|
getActiveDocument: vi.fn(),
|
|
getStore: vi.fn(),
|
|
getViewport: vi.fn(() => ({ left: 0, top: 0, width: 300, height: 300 })),
|
|
setLock: vi.fn(),
|
|
store: createState() as unknown as Store<BitMapperyState>,
|
|
} as unknown as ZoomableCanvas;
|
|
}
|
|
|
|
export function createMockImageElement(): HTMLImageElement {
|
|
return {
|
|
src: "foo",
|
|
width: 300,
|
|
height: 200,
|
|
} as unknown as HTMLImageElement;
|
|
}
|
|
|
|
function createMockCanvasRenderingContext2D() {
|
|
return {
|
|
arc: vi.fn(),
|
|
beginPath: vi.fn(),
|
|
clearRect: vi.fn(),
|
|
clip: vi.fn(),
|
|
closePath: vi.fn(),
|
|
drawImage: vi.fn(),
|
|
fill: vi.fn(),
|
|
fillRect: vi.fn(),
|
|
rect: vi.fn(),
|
|
rotate: vi.fn(),
|
|
save: vi.fn(),
|
|
stroke: vi.fn(),
|
|
translate: vi.fn(),
|
|
restore: vi.fn(),
|
|
canvas: {
|
|
width: 300,
|
|
height: 200,
|
|
},
|
|
} as unknown as CanvasRenderingContext2D;
|
|
}
|
|
|
|
export function createMockCanvasElement(): HTMLCanvasElement {
|
|
const ctx = createMockCanvasRenderingContext2D();
|
|
const cvs = {
|
|
width: 300,
|
|
height: 200,
|
|
getContext: () => ctx,
|
|
} as unknown as HTMLCanvasElement;
|
|
|
|
// @ts-expect-error cannot assign to read only property
|
|
ctx.canvas = cvs;
|
|
|
|
return cvs;
|
|
}
|
|
|
|
export function mockCanvasConstructor(): void {
|
|
vi.spyOn( document, "createElement" ).mockImplementation( type => {
|
|
if ( type === "canvas" ) {
|
|
return createMockCanvasElement() as HTMLElement;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Execute calls debounced by requestAnimationFrame() to use timeouts, which allows
|
|
* us to throttle these with vi.useFakeTimers();
|
|
*
|
|
* Run each RAF callback by invoking vi.runAllTimers();
|
|
* Don't forget to use vi.useRealTimers() and vi.restoreAllMocks() to clean up.
|
|
*/
|
|
export function mockRequestAnimationFrame( now = window.performance.now(), fps = 60 ) {
|
|
vi.spyOn( window, "cancelAnimationFrame" ).mockImplementation( rafId => {
|
|
clearTimeout( rafId );
|
|
});
|
|
|
|
vi.spyOn( window, "requestAnimationFrame" ).mockImplementation( cb => {
|
|
const interval = 1000 / fps;
|
|
const id = setTimeout(() => {
|
|
now += interval;
|
|
cb( now );
|
|
}, interval );
|
|
return id as unknown as number;
|
|
});
|
|
}
|
|
|
|
export function createMockFile( name: string, type = "" ): File {
|
|
const out = new Blob([], { type }) as File;
|
|
// @ts-expect-error name is readonly
|
|
out.name = name;
|
|
|
|
return out;
|
|
}
|
|
|
|
export function createState( props?: Partial<BitMapperyState> ): BitMapperyState {
|
|
return {
|
|
menuOpened: false,
|
|
toolboxOpened: false,
|
|
openedPanels: [],
|
|
selectionContent: null,
|
|
blindActive: false,
|
|
panMode: false,
|
|
selectMode: false,
|
|
layerSelectMode: false,
|
|
dialog: null,
|
|
modal: null,
|
|
loadingStates: [],
|
|
notifications: [],
|
|
storageType: STORAGE_TYPES.LOCAL,
|
|
dropboxConnected: false,
|
|
driveConnected: false,
|
|
windowSize: {
|
|
width: 990,
|
|
height: 600,
|
|
},
|
|
canvas: createCanvasState(),
|
|
document: createDocumentState(),
|
|
history: createHistoryState(),
|
|
image: createImageState(),
|
|
preferences: createPreferencesState(),
|
|
tool: createToolState(),
|
|
...props,
|
|
};
|
|
}
|
|
|
|
export function createMockShape(): Shape {
|
|
return [ { x: 0, y: 0 }, { x: 10, y: 0 }, { x: 10, y: 10 }, { x: 0, y: 0 }];
|
|
}
|
|
|
|
export function createMockSelection(): Selection {
|
|
return [ createMockShape() ];
|
|
}
|