(raw: unknown)
| 75 | } |
| 76 | |
| 77 | export function parseMotionSpec(raw: unknown): MotionSpecParse { |
| 78 | if (!isObject(raw)) return { ok: false, errors: ["spec must be a JSON object"] }; |
| 79 | if (raw.version !== undefined && raw.version !== 1) |
| 80 | return { |
| 81 | ok: false, |
| 82 | errors: [`spec version ${raw.version} is not supported — upgrade the hyperframes CLI`], |
| 83 | }; |
| 84 | if (!Array.isArray(raw.assertions)) |
| 85 | return { ok: false, errors: ['spec must have an "assertions" array'] }; |
| 86 | if ( |
| 87 | raw.duration !== undefined && |
| 88 | (typeof raw.duration !== "number" || !Number.isFinite(raw.duration) || raw.duration <= 0) |
| 89 | ) |
| 90 | return { ok: false, errors: ['"duration" must be a positive number when present'] }; |
| 91 | |
| 92 | const assertions: MotionAssertion[] = []; |
| 93 | const errors: string[] = []; |
| 94 | raw.assertions.forEach((entry, index) => { |
| 95 | const result = validateAssertion(entry, index); |
| 96 | if (typeof result === "string") errors.push(result); |
| 97 | else assertions.push(result); |
| 98 | }); |
| 99 | |
| 100 | if (errors.length > 0) return { ok: false, errors }; |
| 101 | if (assertions.length === 0) return { ok: false, errors: ["spec has no assertions"] }; |
| 102 | |
| 103 | const spec: MotionSpec = { assertions }; |
| 104 | if (typeof raw.duration === "number") spec.duration = raw.duration; |
| 105 | return { ok: true, spec }; |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Locate a `*.motion.json` sidecar in the project dir. When several exist, |
no test coverage detected