2026-05-10 03:06:54 +07:00
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
|
import type { Project } from "@pien-studio/types";
|
|
|
|
|
import { hasProjectChanged } from "./project-equality";
|
|
|
|
|
|
|
|
|
|
function makeProject(): Project {
|
|
|
|
|
return {
|
|
|
|
|
id: "p1",
|
|
|
|
|
title: "Project",
|
|
|
|
|
createdAt: "2024-01-01T00:00:00.000Z",
|
|
|
|
|
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
|
|
|
aspectRatio: "1:1",
|
|
|
|
|
canvas: { width: 100, height: 100, unit: "px" },
|
2026-05-31 03:03:49 +07:00
|
|
|
layers: [textLayer("l1")],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function textLayer(id: string) {
|
|
|
|
|
return {
|
|
|
|
|
id,
|
|
|
|
|
type: "text" as const,
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
width: 120,
|
|
|
|
|
height: 48,
|
|
|
|
|
scale: 1,
|
|
|
|
|
rotation: 0,
|
|
|
|
|
opacity: 1,
|
|
|
|
|
effects: [],
|
|
|
|
|
visible: true,
|
|
|
|
|
text: "Text",
|
|
|
|
|
fontFamily: "system-ui",
|
|
|
|
|
fontSize: 24,
|
|
|
|
|
color: "#000",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function rasterLayer(id: string) {
|
|
|
|
|
return {
|
|
|
|
|
id,
|
|
|
|
|
type: "raster" as const,
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
width: 120,
|
|
|
|
|
height: 80,
|
|
|
|
|
scale: 1,
|
|
|
|
|
rotation: 0,
|
|
|
|
|
opacity: 1,
|
|
|
|
|
effects: [],
|
|
|
|
|
visible: true,
|
|
|
|
|
asset: null,
|
2026-05-10 03:06:54 +07:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
describe("hasProjectChanged", () => {
|
|
|
|
|
it("returns false for equal projects", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
|
|
|
|
expect(hasProjectChanged(a, b)).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("detects canvas changes", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
|
|
|
|
b.canvas.width = 101;
|
|
|
|
|
expect(hasProjectChanged(a, b)).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("detects face blur region changes", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
2026-05-31 03:03:49 +07:00
|
|
|
a.layers[0] = rasterLayer("l1");
|
|
|
|
|
b.layers[0] = rasterLayer("l1");
|
|
|
|
|
a.layers[0].effects = [
|
|
|
|
|
{
|
|
|
|
|
kind: "face-blur",
|
|
|
|
|
enabled: true,
|
|
|
|
|
method: "gaussian",
|
|
|
|
|
amount: 14,
|
|
|
|
|
regions: [{ x: 1, y: 1, width: 10, height: 10 }],
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
b.layers[0].effects = [
|
|
|
|
|
{
|
|
|
|
|
kind: "face-blur",
|
|
|
|
|
enabled: true,
|
|
|
|
|
method: "gaussian",
|
|
|
|
|
amount: 14,
|
|
|
|
|
regions: [{ x: 1, y: 1, width: 11, height: 10 }],
|
|
|
|
|
},
|
|
|
|
|
];
|
2026-05-10 03:06:54 +07:00
|
|
|
expect(hasProjectChanged(a, b)).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("detects layer order changes", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
2026-05-31 03:03:49 +07:00
|
|
|
a.layers.push({ ...textLayer("l2"), x: 3, y: 4 });
|
|
|
|
|
b.layers.push({ ...textLayer("l2"), x: 3, y: 4 });
|
2026-05-10 03:06:54 +07:00
|
|
|
b.layers = [b.layers[1], b.layers[0]];
|
|
|
|
|
expect(hasProjectChanged(a, b)).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-24 21:05:21 +07:00
|
|
|
it("detects visibility changes", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
|
|
|
|
b.layers[0].visible = false;
|
|
|
|
|
expect(hasProjectChanged(a, b)).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-10 03:06:54 +07:00
|
|
|
it("treats missing optional fields and undefined as equal", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
|
|
|
|
a.layers[0].name = undefined;
|
|
|
|
|
b.layers[0].name = undefined;
|
|
|
|
|
expect(hasProjectChanged(a, b)).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("detects face blur removal", () => {
|
|
|
|
|
const a = makeProject();
|
|
|
|
|
const b = makeProject();
|
2026-05-31 03:03:49 +07:00
|
|
|
a.layers[0] = rasterLayer("l1");
|
|
|
|
|
b.layers[0] = rasterLayer("l1");
|
|
|
|
|
a.layers[0].effects = [
|
|
|
|
|
{
|
|
|
|
|
kind: "face-blur",
|
|
|
|
|
enabled: true,
|
|
|
|
|
method: "gaussian",
|
|
|
|
|
amount: 14,
|
|
|
|
|
regions: [{ x: 1, y: 1, width: 10, height: 10 }],
|
|
|
|
|
},
|
|
|
|
|
];
|
2026-05-10 03:06:54 +07:00
|
|
|
expect(hasProjectChanged(a, b)).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
});
|