136 lines
3.6 KiB
TypeScript
136 lines
3.6 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
createEmptyResourceCanvasLayout,
|
|
moveResourceCanvasPosition,
|
|
reconcileResourceCanvasLayout,
|
|
RESOURCE_CANVAS_CARD_HEIGHT,
|
|
RESOURCE_CANVAS_CARD_WIDTH,
|
|
RESOURCE_CANVAS_COLUMN_GAP,
|
|
RESOURCE_CANVAS_ROW_GAP,
|
|
type ResourceCanvasItem,
|
|
} from '../src/view/project-development/resourceCanvasLayoutModel';
|
|
|
|
function resource(
|
|
id: string,
|
|
category: ResourceCanvasItem['category'],
|
|
dependencyDepth = 0,
|
|
): ResourceCanvasItem {
|
|
return {
|
|
id,
|
|
category,
|
|
dependencyDepth,
|
|
label: id,
|
|
mediaType: category === 'art' ? 'image/png' : 'text/markdown',
|
|
};
|
|
}
|
|
|
|
describe('resource canvas layout model', () => {
|
|
it('creates non-overlapping defaults and keeps the two modes independent', () => {
|
|
const resources = [
|
|
resource('a', 'art', 0),
|
|
resource('b', 'art', 0),
|
|
resource('c', 'art', 1),
|
|
];
|
|
const dependency = reconcileResourceCanvasLayout(
|
|
createEmptyResourceCanvasLayout('project-1', 'dependency'),
|
|
resources,
|
|
).layout;
|
|
const type = reconcileResourceCanvasLayout(
|
|
createEmptyResourceCanvasLayout('project-1', 'type'),
|
|
resources,
|
|
).layout;
|
|
|
|
expect(dependency.positions).toMatchObject([
|
|
{ resourceId: 'a', x: 0, y: 0, manuallyPlaced: false },
|
|
{
|
|
resourceId: 'c',
|
|
x: RESOURCE_CANVAS_CARD_WIDTH + RESOURCE_CANVAS_COLUMN_GAP,
|
|
y: 0,
|
|
manuallyPlaced: false,
|
|
},
|
|
{
|
|
resourceId: 'b',
|
|
x: 0,
|
|
y: RESOURCE_CANVAS_CARD_HEIGHT + RESOURCE_CANVAS_ROW_GAP,
|
|
manuallyPlaced: false,
|
|
},
|
|
]);
|
|
expect(type.positions).toMatchObject([
|
|
{ resourceId: 'a', x: 0, y: 0 },
|
|
{
|
|
resourceId: 'b',
|
|
x: RESOURCE_CANVAS_CARD_WIDTH + RESOURCE_CANVAS_COLUMN_GAP,
|
|
y: 0,
|
|
},
|
|
{
|
|
resourceId: 'c',
|
|
x: 2 * (RESOURCE_CANVAS_CARD_WIDTH + RESOURCE_CANVAS_COLUMN_GAP),
|
|
y: 0,
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('preserves existing positions, appends new resources, and removes stale ids', () => {
|
|
const base = reconcileResourceCanvasLayout(
|
|
createEmptyResourceCanvasLayout('project-1', 'type'),
|
|
[resource('a', 'document'), resource('stale', 'document')],
|
|
).layout;
|
|
const moved = moveResourceCanvasPosition(
|
|
base,
|
|
'a',
|
|
'document',
|
|
333.4,
|
|
41.6,
|
|
);
|
|
const reconciled = reconcileResourceCanvasLayout(moved, [
|
|
resource('a', 'document'),
|
|
resource('new', 'document'),
|
|
]);
|
|
|
|
expect(reconciled.changed).toBe(true);
|
|
expect(reconciled.layout.positions).toContainEqual({
|
|
resourceId: 'a',
|
|
section: 'document',
|
|
x: 333,
|
|
y: 42,
|
|
manuallyPlaced: true,
|
|
});
|
|
expect(
|
|
reconciled.layout.positions.some(
|
|
(position) => position.resourceId === 'stale',
|
|
),
|
|
).toBe(false);
|
|
expect(
|
|
reconciled.layout.positions.find(
|
|
(position) => position.resourceId === 'new',
|
|
)?.manuallyPlaced,
|
|
).toBe(false);
|
|
});
|
|
|
|
it('drops a persisted position whose section no longer matches the resource', () => {
|
|
const layout = createEmptyResourceCanvasLayout('project-1', 'dependency');
|
|
layout.positions = [
|
|
{
|
|
resourceId: 'asset-a',
|
|
section: 'audio',
|
|
x: 10,
|
|
y: 10,
|
|
manuallyPlaced: true,
|
|
},
|
|
];
|
|
const reconciled = reconcileResourceCanvasLayout(layout, [
|
|
resource('asset-a', 'art'),
|
|
]);
|
|
expect(reconciled.layout.positions).toEqual([
|
|
{
|
|
resourceId: 'asset-a',
|
|
section: 'art',
|
|
x: 0,
|
|
y: 0,
|
|
manuallyPlaced: false,
|
|
},
|
|
]);
|
|
});
|
|
});
|