mirror of
https://github.com/igorski/bitmappery.git
synced 2026-07-16 20:08:42 +02:00
Split `definitions/document.ts` into unique files per actor type. Create `model` folder to store the above types, their factories and the state changing actions.
154 lines
5.7 KiB
TypeScript
154 lines
5.7 KiB
TypeScript
import { it, afterEach, beforeEach, describe, expect, vi } from "vitest";
|
|
import { createMockCanvasElement, mockZCanvas } from "../../mocks";
|
|
|
|
mockZCanvas();
|
|
|
|
import { type Layer } from "@/model/types/layer";
|
|
import DocumentFactory from "@/model/factories/document-factory";
|
|
import LayerFactory from "@/model/factories/layer-factory";
|
|
import LayerRenderer from "@/rendering/actors/layer-renderer";
|
|
import { positionLayer } from "@/model/actions/layer-position";
|
|
|
|
const mockGetRendererForLayer = vi.fn();
|
|
vi.mock( "@/model/factories/renderer-factory", () => ({
|
|
getRendererForLayer: vi.fn(( ...args ) => mockGetRendererForLayer( ...args )),
|
|
}));
|
|
|
|
const mockEnqueueState = vi.fn();
|
|
vi.mock( "@/model/factories/history-state-factory", () => ({
|
|
enqueueState: vi.fn(( ...args ) => mockEnqueueState( ...args )),
|
|
}));
|
|
|
|
const mockFlushBlendedLayerCache = vi.fn();
|
|
let mockUseBlendCaching = false;
|
|
vi.mock( "@/rendering/cache/blended-layer-cache", () => ({
|
|
flushBlendedLayerCache: vi.fn(() => mockFlushBlendedLayerCache()),
|
|
useBlendCaching: vi.fn(() => mockUseBlendCaching ),
|
|
isBlendCached: vi.fn(),
|
|
}));
|
|
|
|
const mockCreateLayerThumbnail = vi.fn();
|
|
vi.mock( "@/rendering/cache/thumbnail-cache", () => ({
|
|
createLayerThumbnail: vi.fn(( ...args ) => mockCreateLayerThumbnail( ...args )),
|
|
}));
|
|
|
|
describe( "Layer positioning action", () => {
|
|
const activeDocument = DocumentFactory.create();
|
|
let layer: Layer;
|
|
let layerRenderer: LayerRenderer;
|
|
|
|
beforeEach(() => {
|
|
layer = LayerFactory.create({
|
|
source: createMockCanvasElement(),
|
|
mask: createMockCanvasElement(),
|
|
});
|
|
layerRenderer = new LayerRenderer( layer );
|
|
mockGetRendererForLayer.mockReturnValue( layerRenderer );
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
describe( "When storing a Layer position as a history state", () => {
|
|
const oldLayerX = 5;
|
|
const oldLayerY = 6;
|
|
const newLayerX = 15;
|
|
const newLayerY = 16;
|
|
const oldRendererX = 2;
|
|
const oldRendererY = 3;
|
|
const newRendererX = 7;
|
|
const newRendererY = 8;
|
|
|
|
it( "should enqueue the state in history", () => {
|
|
positionLayer(
|
|
layer, activeDocument, oldLayerX, oldLayerY, newLayerX, newLayerY,
|
|
oldRendererX, oldRendererY, newRendererX, newRendererY
|
|
);
|
|
expect( mockEnqueueState ).toHaveBeenCalledWith(
|
|
`layerPos_${layer.id}`, {
|
|
undo: expect.any( Function ),
|
|
redo: expect.any( Function )
|
|
}
|
|
);
|
|
});
|
|
|
|
describe( "and calling the undo or redo state", () => {
|
|
let undo: VoidFunction;
|
|
let redo: VoidFunction;
|
|
|
|
beforeEach(() => {
|
|
positionLayer(
|
|
layer, activeDocument, oldLayerX, oldLayerY, newLayerX, newLayerY,
|
|
oldRendererX, oldRendererY, newRendererX, newRendererY
|
|
);
|
|
({ undo, redo } = mockEnqueueState.mock.calls[ 0 ][ 1 ]);
|
|
});
|
|
|
|
it.each([ "undo", "redo" ])
|
|
( `should restore the position of the layer for the "%s" action`, ( action: string ) => {
|
|
layer.left = 1000;
|
|
layer.top = 1000;
|
|
|
|
( action === "undo" ) ? undo() : redo();
|
|
|
|
expect( layer.left ).toEqual( action === "undo" ? oldLayerX : newLayerX );
|
|
expect( layer.top ).toEqual( action === "undo" ? oldLayerY : newLayerY );
|
|
});
|
|
|
|
it.each([ "undo", "redo" ])
|
|
( `should update the existing bounds object directly without invoking the setter methods for the "%s" action`,
|
|
( action: string ) => {
|
|
const bounds = layerRenderer.getBounds();
|
|
const { width, height } = bounds;
|
|
|
|
bounds.left = 1000;
|
|
bounds.top = 1000;
|
|
|
|
( action === "undo" ) ? undo() : redo();
|
|
|
|
expect( bounds ).toEqual({
|
|
left: action === "undo" ? oldRendererX : newRendererX,
|
|
top: action === "undo" ? oldRendererY : newRendererY,
|
|
width,
|
|
height,
|
|
});
|
|
});
|
|
|
|
it.each([ "undo", "redo" ])
|
|
( `should call the invalidate() method on the renderer to trigger a render for the "%s" action`, ( action: string ) => {
|
|
const invalidateSpy = vi.spyOn( layerRenderer, "invalidate" );
|
|
|
|
( action === "undo" ) ? undo() : redo();
|
|
|
|
expect( invalidateSpy ).toHaveBeenCalled();
|
|
});
|
|
|
|
it.each([ "undo", "redo" ])
|
|
( `should not invalidate the blended layer cache when blend caching is disabled for the "%s" action`, ( action: string ) => {
|
|
mockUseBlendCaching = false;
|
|
|
|
( action === "undo" ) ? undo() : redo();
|
|
|
|
expect( mockFlushBlendedLayerCache ).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it.each([ "undo", "redo" ])
|
|
( `should invalidate the blended layer cache when blend caching is enabled for the "%s" action`, ( action: string ) => {
|
|
mockUseBlendCaching = true;
|
|
|
|
( action === "undo" ) ? undo() : redo();
|
|
|
|
expect( mockFlushBlendedLayerCache ).toHaveBeenCalled();
|
|
});
|
|
|
|
it.each([ "undo", "redo" ])
|
|
( `should request to recreate the layer thumbnail for the "%s" action`, ( action: string ) => {
|
|
( action === "undo" ) ? undo() : redo();
|
|
|
|
expect( mockCreateLayerThumbnail ).toHaveBeenCalledWith( layer, activeDocument, true );
|
|
});
|
|
});
|
|
});
|
|
});
|