mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(lint): reject parser-invalid variable defaults (#5314)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// fallow-ignore-file code-duplication
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { lintHyperframeHtml } from "../hyperframeLinter.js";
|
||||
import { parseCompositionVariables } from "@hyperframes/parsers/composition";
|
||||
|
||||
describe("composition rules", () => {
|
||||
describe("canonical timing contract", () => {
|
||||
@@ -1222,6 +1223,65 @@ describe("composition rules", () => {
|
||||
});
|
||||
|
||||
describe("invalid_composition_variables_declaration", () => {
|
||||
const invalidDeclarations = [
|
||||
{ id: "setting", type: "string", label: "Setting", default: 3 },
|
||||
{ id: "setting", type: "number", label: "Setting", default: "3" },
|
||||
{ id: "setting", type: "boolean", label: "Setting", default: "false" },
|
||||
{ id: "setting", type: "color", label: "Setting", default: 3 },
|
||||
{ id: "setting", type: "font", label: "Setting", default: 3 },
|
||||
{ id: "setting", type: "image", label: "Setting", default: 3 },
|
||||
{ id: "setting", type: "enum", label: "Setting", default: 3, options: [] },
|
||||
{ id: "setting", type: "enum", label: "Setting", default: "light" },
|
||||
{ id: "setting", type: "enum", label: "Setting", default: "light", options: "light" },
|
||||
];
|
||||
|
||||
for (const placement of ["html", "root", "template"]) {
|
||||
it.each(invalidDeclarations)(
|
||||
`reports parser-rejected declaration %j on ${placement}`,
|
||||
async (declaration) => {
|
||||
const attribute = `data-composition-variables='${JSON.stringify([declaration])}'`;
|
||||
const root = `<div data-composition-id="main" data-no-timeline data-width="1920" data-height="1080" data-duration="2" ${placement === "html" ? "" : attribute}></div>`;
|
||||
const html =
|
||||
placement === "template"
|
||||
? `<template>${root}</template>`
|
||||
: `<html ${placement === "html" ? attribute : ""}><body>${root}</body></html>`;
|
||||
const element = document.createElement("div");
|
||||
element.setAttribute("data-composition-variables", JSON.stringify([declaration]));
|
||||
expect(parseCompositionVariables(element)).toEqual([]);
|
||||
const result = await lintHyperframeHtml(html, {
|
||||
isSubComposition: placement === "template",
|
||||
});
|
||||
const findings = result.findings.filter(
|
||||
(finding) => finding.code === "invalid_composition_variables_declaration",
|
||||
);
|
||||
expect(findings).toHaveLength(1);
|
||||
expect(findings[0]?.message).toMatch(/\[0\]/);
|
||||
expect(findings[0]?.severity).toBe("error");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
it.each([
|
||||
{ id: "setting", type: "string", label: "Setting", default: "" },
|
||||
{ id: "setting", type: "number", label: "Setting", default: 0 },
|
||||
{ id: "setting", type: "boolean", label: "Setting", default: false },
|
||||
{ id: "setting", type: "color", label: "Setting", default: "#fff" },
|
||||
{ id: "setting", type: "font", label: "Setting", default: "Arial" },
|
||||
{ id: "setting", type: "image", label: "Setting", default: "assets/a.png" },
|
||||
{ id: "setting", type: "enum", label: "Setting", default: "light", options: [] },
|
||||
])("preserves parser-admitted declaration %j", async (declaration) => {
|
||||
const element = document.createElement("div");
|
||||
element.setAttribute("data-composition-variables", JSON.stringify([declaration]));
|
||||
expect(parseCompositionVariables(element)).toEqual([declaration]);
|
||||
const html = `<html data-composition-variables='${JSON.stringify([declaration])}'><body><div data-composition-id="main" data-no-timeline data-width="1920" data-height="1080" data-duration="2"></div></body></html>`;
|
||||
const result = await lintHyperframeHtml(html);
|
||||
expect(
|
||||
result.findings.filter(
|
||||
(finding) => finding.code === "invalid_composition_variables_declaration",
|
||||
),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("checks a declaration on the composition root too", async () => {
|
||||
const html = `<html><body><div data-composition-id="x" data-composition-variables='[{"id":12345}]'></div></body></html>`;
|
||||
const result = await lintHyperframeHtml(html);
|
||||
|
||||
@@ -11,7 +11,11 @@ import {
|
||||
truncateSnippet,
|
||||
WINDOW_TIMELINE_ASSIGN_PATTERN,
|
||||
} from "../utils";
|
||||
import { COMPOSITION_VARIABLE_TYPES, isSafeMediaUrl } from "@hyperframes/parsers/composition";
|
||||
import {
|
||||
COMPOSITION_VARIABLE_TYPES,
|
||||
isCompositionVariable,
|
||||
isSafeMediaUrl,
|
||||
} from "@hyperframes/parsers/composition";
|
||||
import { COMPOSITION_ATTRIBUTES, readClipTiming } from "@hyperframes/parsers/composition-contract";
|
||||
import { resolveCompositionDuration } from "@hyperframes/parsers/composition-duration";
|
||||
import {
|
||||
@@ -482,6 +486,17 @@ function variablesDeclarationFindings(
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (!isCompositionVariable(e)) {
|
||||
findings.push({
|
||||
code: "invalid_composition_variables_declaration",
|
||||
severity: "error",
|
||||
message: `data-composition-variables entry [${i}] has a default that does not match its type, or an enum without an options array.`,
|
||||
fixHint:
|
||||
"Use number defaults for number variables, boolean defaults for boolean variables, and string defaults for other types. Enum variables also require an options array.",
|
||||
snippet: truncateSnippet(tag.raw),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const id = String(e.id);
|
||||
if (
|
||||
(e.type === "image" || varSrcIds.has(id)) &&
|
||||
|
||||
Reference in New Issue
Block a user