fix(tui): correct ink-form's misspelled incomplete-form hint

The hint under a form with unfilled required fields reads "you have not
competed yet". The string is upstream's, hardcoded in
`ink-form/lib/SubmitButton.js` with no prop to override it, and `ink-form`
was last published in 2024 — but it renders in the Inspector's tool,
prompt, and resource test forms, so it is ours to fix in practice.

Bundling `ink-form` (previous commit) is what makes it patchable: an
esbuild `onLoad` hook rewrites the label as the file enters the bundle.
The hook throws when the string is absent rather than passing the source
through, so an `ink-form` upgrade cannot silently retire the patch or
leave it aimed at a string that no longer exists — the tests drive it
against the real dependency source for the same reason.

Reported upstream as lukasbach/ink-form#14.

Closes #1952

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLYmVPVLdeYpE6aMTUsCks
This commit is contained in:
cliffhall 2026-08-11 23:15:35 -04:00
commit 3c1bbbcb5f

View file

@ -25,7 +25,10 @@ import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import type { Options } from "tsup";
import tsupConfig from "../tsup.config.js";
import tsupConfig, {
INK_FORM_INCOMPLETE_HINT,
fixInkFormIncompleteHint,
} from "../tsup.config.js";
const clientDir = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
@ -120,6 +123,40 @@ describe("tui tsup config", () => {
}
});
it("corrects ink-form's misspelled incomplete-form hint", () => {
// Read the real dependency, so an `ink-form` upgrade that fixes or rewords
// the label fails here — the patch must then be removed, not left silently
// matching nothing.
const submitButton = readFileSync(
path.join(
clientDir,
"node_modules",
"ink-form",
"lib",
"SubmitButton.js",
),
"utf8",
);
const patched = fixInkFormIncompleteHint(submitButton, "SubmitButton.js");
expect(patched).toContain(INK_FORM_INCOMPLETE_HINT.fixed);
expect(patched).not.toContain(INK_FORM_INCOMPLETE_HINT.typo);
});
it("fails loudly rather than silently skipping a label it cannot find", () => {
expect(() =>
fixInkFormIncompleteHint("no such label here", "SubmitButton.js"),
).toThrow(/no longer contains the ink-form label/);
});
it("only rewrites the misspelling", () => {
// The two strings must differ by exactly the fix, or the patch is silently
// changing copy nobody reviewed.
expect(INK_FORM_INCOMPLETE_HINT.fixed).toBe(
INK_FORM_INCOMPLETE_HINT.typo.replace("competed", "completed"),
);
});
it("verifies the deps it exempts are still declared", () => {
// If `ink` ever leaves the dependency list, the exemption above is stale
// and would silently excuse a future package that took its name.