Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ pre-commit:
# fails on issues introduced by the branch, not inherited findings.
fallow:
glob: "packages/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}"
run: bunx fallow audit --base origin/main --fail-on-issues
# Unset git worktree env vars: fallow creates a temp worktree internally and
# GIT_DIR/GIT_INDEX_FILE (set by git in worktree hook context) break that.
# env -u is safe in non-worktree contexts (no-op when var is unset).
run: env -u GIT_DIR -u GIT_INDEX_FILE -u GIT_WORK_TREE bunx fallow audit --base origin/main --fail-on-issues
filesize:
# Scoped to packages/studio — the 600 LOC limit is a studio architecture
# standard enforced as part of the App.tsx decomposition work. Player and
Expand Down
19 changes: 1 addition & 18 deletions packages/core/src/parsers/htmlParser.roundtrip.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,8 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { parseHtml } from "./htmlParser.js";
import { maxEndTime, serialize } from "./test-utils.js";
import { generateHyperframesHtml } from "../generators/hyperframes.js";
import type { ParsedHtml } from "./htmlParser.js";

function maxEndTime(elements: ParsedHtml["elements"]): number {
if (elements.length === 0) return 0;
return Math.max(...elements.map((e) => e.startTime + e.duration));
}

function serialize(parsed: ParsedHtml): string {
// Fixed compositionId prevents Date.now() churn from masking structural instability.
// The compositionId generation instability itself is tracked as R1 (stable hf- ids).
return generateHyperframesHtml(parsed.elements, maxEndTime(parsed.elements), {
compositionId: "test-comp",
resolution: parsed.resolution,
styles: parsed.styles ?? undefined,
keyframes: parsed.keyframes,
stageZoomKeyframes: parsed.stageZoomKeyframes,
});
}

describe("T1 — parse→serialize round-trip (DOM/timing)", () => {
it("preserves element count and ids through one round-trip", () => {
Expand Down
18 changes: 1 addition & 17 deletions packages/core/src/parsers/stableIds.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,7 @@
*/
import { describe, expect, it } from "vitest";
import { parseHtml } from "./htmlParser.js";
import { generateHyperframesHtml } from "../generators/hyperframes.js";
import type { ParsedHtml } from "./htmlParser.js";

function maxEndTime(elements: ParsedHtml["elements"]): number {
if (elements.length === 0) return 0;
return Math.max(...elements.map((e) => e.startTime + e.duration));
}

function serialize(parsed: ParsedHtml): string {
return generateHyperframesHtml(parsed.elements, maxEndTime(parsed.elements), {
compositionId: "test-comp",
resolution: parsed.resolution,
styles: parsed.styles ?? undefined,
keyframes: parsed.keyframes,
stageZoomKeyframes: parsed.stageZoomKeyframes,
});
}
import { serialize } from "./test-utils.js";

describe("T2 — stable element ids (spec for R1)", () => {
// --- Spec (red until R1) ---
Expand Down
28 changes: 28 additions & 0 deletions packages/core/src/parsers/test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Shared test utilities for parser test suites (T1, T2, T6…).
* Import from here rather than duplicating helpers across test files.
*
* Not part of the public package exports — consumed only by *.test.ts files.
*/
import { generateHyperframesHtml } from "../generators/hyperframes.js";
import type { ParsedHtml } from "./htmlParser.js";

export function maxEndTime(elements: ParsedHtml["elements"]): number {
if (elements.length === 0) return 0;
return Math.max(...elements.map((e) => e.startTime + e.duration));
}

/**
* Round-trip serialize helper.
* Fixed compositionId prevents Date.now() churn from masking structural instability.
* The compositionId generation instability itself is tracked as R1 (stable hf- ids).
*/
export function serialize(parsed: ParsedHtml): string {
return generateHyperframesHtml(parsed.elements, maxEndTime(parsed.elements), {
compositionId: "test-comp",
resolution: parsed.resolution,
styles: parsed.styles ?? undefined,
keyframes: parsed.keyframes,
stageZoomKeyframes: parsed.stageZoomKeyframes,
});
}
51 changes: 51 additions & 0 deletions packages/core/src/studio-api/helpers/previewAdapter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* T10 — PreviewAdapter contract (spec for R7).
*
* `createPreviewAdapter` does not exist yet. These stubs define the expected
* interface so R7 has a concrete target. Convert from it.todo to real
* assertions in the R7 PR.
*
* Hit-testing (elementAtPoint) in both linkedom and jsdom returns null for
* all geometry calls — the real tests must inject a position-resolver stub
* or mock elementFromPoint. The contract tested is filtering logic (root
* exclusion, data-hf-id ancestor walk, opacity-at-playhead), not geometry.
*/
import { describe, it } from "vitest";

describe("T10 — PreviewAdapter contract (spec for R7)", () => {
describe("elementAtPoint", () => {
it.todo("returns null for the stage root (data-hf-root)");

it.todo("returns the nearest ancestor with data-hf-id");

it.todo("returns null when the hit element has no data-hf-id ancestor");

it.todo("skips elements whose computed opacity is 0 at the given playhead time");
});

describe("applyDraft / revertDraft", () => {
it.todo("applyDraft writes --hf-studio-* CSS props and sets the gesture marker");

it.todo("applyDraft accepts both move (dx/dy) and resize (w/h) payloads");

it.todo("revertDraft removes draft props and clears the gesture marker");

it.todo("revertDraft restores original translate when an original was recorded");
});

describe("commitPreview", () => {
it.todo("returns null when no gesture marker is present");

it.todo("derives a moveElement patch from draft markers on commit");

it.todo("derives a resize patch from draft markers on commit");

it.todo("clears the gesture marker after commit");
});

describe("getElementTimings", () => {
it.todo("reads authored absolute times from data-start / data-end");

it.todo("ignores elements without data-hf-id");
});
});
9 changes: 8 additions & 1 deletion packages/core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,12 @@
},
"files": ["src/runtime/mediaVolumeEnvelope.ts"],
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "src/tests", "src/runtime", "**/*.test.ts"]
"exclude": [
"node_modules",
"dist",
"src/tests",
"src/runtime",
"**/*.test.ts",
"src/parsers/test-utils.ts"
]
}
Loading
Loading