test(runtime): lock reconciler, measure, flex, overflow, build-output (Ink parity) (#116)

Final round-2 test-only batch (behaviors already at parity with Ink reconciler.tsx,
measure-text.tsx, flex-*.tsx, overflow.tsx, build-output.ts):
- build-output: every package.json export target resolves on disk (runtime/cli/testing)
  + the .d.mts declaration sibling for the typed libraries (runtime/testing, not cli).
- reconciler: keyed insert-between [a,c]→[a,b,c]; replace a colored <Text> child with a
  plain string; setElementText A→B + the text-context guard; marginLeft removal reset.
- measure: empty <Text> contributes height 0 in a column; non-zero left (marginLeft=5 →
  5,1); measureTextNatural trailing/only-newline heights.
- flex: alignSelf='auto' == default + alignSelf removal resets to AUTO; the two
  space-around known-yoga-bug cases converted from test.skip to test.fails (they assert
  the DESIRED output and flip to a real failure if yoga ever fixes the bug); the documented
  flexDirection/flexWrap removal-reset divergence (was comment-only) now has a visual lock.
- overflow: out-of-bounds writes produce Ink's exact clipped frame (sparse past-width cell,
  filtered hole) — tightened from toBeDefined().
- components: inline + top-level non-empty fragment in <Text>; the previously-skipped
  ST-terminated OSC-8 hyperlink hard-wrap now passes ('abcde\nfghij') — un-skipped as a lock.

Codex-reviewed GENUINE.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yunfei He
2026-06-01 03:28:35 +08:00
committed by GitHub
parent 7d6a92ea15
commit 48558c5af6
10 changed files with 457 additions and 12 deletions
@@ -47,6 +47,33 @@ describe("useBoxMetrics", () => {
expect(pos.value.t).toBe(0);
});
// Ink use-box-metrics.tsx:37-61 ("returns correct position"): a tracked box on
// the SECOND row of a column with marginLeft=5 must report left=5 (the margin)
// and top=1 (the row below the first line).
test("returns non-zero left/top for an offset box on the second row", async () => {
const pos = shallowRef({ l: -1, t: -1 });
const App = defineComponent(() => {
const boxRef = ref(null);
const metrics = useBoxMetrics(boxRef);
watchEffect(() => {
pos.value = { l: metrics.left.value, t: metrics.top.value };
});
return () => (
<Box flexDirection="column">
<Text>first line</Text>
<Box ref={boxRef} marginLeft={5}>
<Text>tracked</Text>
</Box>
</Box>
);
});
await render(App, { columns: 100 });
await nextTick();
// marginLeft=5 → left=5; second row → top=1.
expect(pos.value.l).toBe(5);
expect(pos.value.t).toBe(1);
});
test("hasMeasured starts false", async () => {
let measured = false;
const App = defineComponent(() => {