test(ui-models): cover reading a stored capacity back out of a row

Every capacity assertion typed into the field first, so the path that reads a
stored count — the one an already-configured route takes every time it is
opened — was never exercised, and the coverage gate said so. A row now opens
on stored counts and is expected to spell them `1M` and `256K`, the same
vocabulary the field accepts.

`capacityText` takes the row it is rendering rather than looking it up again
by index, which retires the impossible empty-row branch that lookup needed.
The list editor's pre-flight model check is unreachable from the card that
disables submit on the same failure, and says so where it stands.
This commit is contained in:
Yichen Jiang
2026-08-05 21:12:45 +08:00
committed by imccyu
parent 3a3abc2bc4
commit dd36db5434
3 changed files with 28 additions and 4 deletions

View File

@@ -177,8 +177,8 @@ export function ModelListEditor(props: ModelListEditorProps): ReactNode {
}
/** What a capacity field shows: the buffer while typing, else the stored count. */
const capacityText = (index: number, field: CapacityField): string =>
editing.get(bufferKey(index, field)) ?? capacitySpelling(numberOf(models[index] ?? {}, field))
const capacityText = (model: ModelDraft, index: number, field: CapacityField): string =>
editing.get(bufferKey(index, field)) ?? capacitySpelling(numberOf(model, field))
/** Drop one row's entries and shift the rows after it down, in one pass. */
const reindexOnRemove = (
@@ -388,7 +388,7 @@ export function ModelListEditor(props: ModelListEditorProps): ReactNode {
className={styles['input']}
type="text"
inputMode="numeric"
value={capacityText(index, 'contextWindow')}
value={capacityText(model, index, 'contextWindow')}
placeholder={CAPACITY_HINT.contextWindow}
aria-label={`${t('modelContextWindow')} ${index + 1}`}
disabled={disabled}
@@ -401,7 +401,7 @@ export function ModelListEditor(props: ModelListEditorProps): ReactNode {
className={styles['input']}
type="text"
inputMode="numeric"
value={capacityText(index, 'maxTokens')}
value={capacityText(model, index, 'maxTokens')}
placeholder={CAPACITY_HINT.maxTokens}
aria-label={`${t('modelMaxTokens')} ${index + 1}`}
disabled={disabled}

View File

@@ -202,7 +202,12 @@ export function ProviderEditor(props: ProviderEditorProps): ReactNode {
? setPath(draft, ['apiKeyEnv'], keyRef)
: draft
{
// The same checker gates the submit button, so a card cannot reach this
// with a bad row; it stays because the schema check below would refuse
// the write with a message naming a path instead of the row, and because
// nothing but this function decides what is written.
const failure = validateDeepSeekModels(getPath(next, ['models']))
/* v8 ignore next 3 -- unreachable from the card: the same failure disables submit */
if (failure !== undefined) {
return `${t('model')} ${String(failure.index + 1)}: ${t(failure.key)}`
}