Skip to content

Add min/max cross-validation to NumberAttributesEditor#722

Merged
alistair3149 merged 1 commit intomasterfrom
fix/476-polish-number-min-max-ui
Apr 16, 2026
Merged

Add min/max cross-validation to NumberAttributesEditor#722
alistair3149 merged 1 commit intomasterfrom
fix/476-polish-number-min-max-ui

Conversation

@JeroenDeDauw
Copy link
Copy Markdown
Member

@JeroenDeDauw JeroenDeDauw commented Apr 14, 2026

Prompted by @JeroenDeDauw, implemented autonomously by Claude Code.
Context: the NeoWiki codebase, issue #476 and comment, and TextAttributesEditor as reference.
Written by Claude Code, Opus 4.6

Fixes #476

NumberAttributesEditor was missing the validation refinements that
TextAttributesEditor received in PR #551. This adds:

  • Error state when minimum exceeds maximum (and vice versa)
  • Local input refs with watchers for all fields (minimum, maximum,
    and precision) so in-progress input is preserved even when invalid
  • New i18n message neowiki-property-editor-min-exceeds-max
  • Extracted shared minExceedsMax helper used by both Text and Number
    editors
  • Moved FieldProps test interface to shared VueTestHelpers
  • CSS classes on min/max fields for robust test selectors

@JeroenDeDauw JeroenDeDauw force-pushed the fix/476-polish-number-min-max-ui branch 2 times, most recently from 0c9d0ae to e30bc32 Compare April 14, 2026 23:04
@JeroenDeDauw JeroenDeDauw marked this pull request as ready for review April 15, 2026 12:27
@alistair3149
Copy link
Copy Markdown
Member

alistair3149 commented Apr 15, 2026

Code review requested by @alistair3149.
Context: the NeoWiki codebase, PR #722 diff, TextAttributesEditor reference from PR #551, and AGENTS.md conventions.
Written by Claude Code, Opus 4.6

Issues

Important

1. Precision field still has the exact bug this PR fixes for min/max.

File: resources/ext.neowiki/src/components/SchemaEditor/Property/NumberAttributesEditor.vue:42-47, 78-88

updatePrecision reads property.precision directly and never mirrors into a local ref. When invalid input is typed (e.g. -5), precisionError is set but nothing is emitted — so the parent's property.precision never updates, the reactivity of precisionError triggers a re-render, and :model-value re-evaluates to the old prop value, snapping the display back and losing the user's -5.

Suggested fix (~5 lines, matches the min/max pattern just established):

const precisionInput = ref( props.property.precision?.toString() ?? '' );

watch( () => props.property.precision, ( newVal ) => {
    precisionInput.value = newVal?.toString() ?? '';
} );

const updatePrecision = ( value: string ): void => {
    precisionInput.value = value;
    const numValue = parseNumber( value );
    // ...rest unchanged
};

And bind :model-value="precisionInput" in the template.

The existing test 'shows error and does not emit when precision is negative' (NumberAttributesEditor.spec.ts:151) only asserts error status and no emit — it starts from precision: undefined, so it can't observe the snap-back. A regression test for this specific behavior should be added (and will fail against the current code, confirming the bug):

it( 'preserves invalid input in the precision field', async () => {
    const wrapper = newWrapper( {
        property: newNumberProperty( { precision: 2 } ),
    } );
    const inputs = wrapper.findAllComponents( CdxTextInput );

    await inputs[ 2 ].vm.$emit( 'update:modelValue', '-5' );

    expect( inputs[ 2 ].props( 'modelValue' ) ).toBe( '-5' );
} );

The same pattern is worth adding for min/max — neither the Text nor Number spec currently exercises the watcher that re-syncs the local input when the parent updates the prop externally, and that's the subtlest part of the in-progress-input preservation.

2. minExceedsMax is duplicated byte-for-byte across two components.

  • resources/ext.neowiki/src/components/SchemaEditor/Property/NumberAttributesEditor.vue:79-83
  • resources/ext.neowiki/src/components/SchemaEditor/Property/TextAttributesEditor.vue:107-111

AGENTS.md explicitly says not to duplicate in production code. Now is the right moment to extract to a shared helper — the second copy just arrived.

Minor

3. Fragile positional indexing in test helpers.

File: resources/ext.neowiki/tests/components/SchemaEditor/Property/NumberAttributesEditor.spec.ts:32-40

fields[length - 3] / length - 2 breaks opaquely if another CdxField is ever added. Prefer class-based lookup (e.g. number-attributes__minimum / __maximum) matching the style the precision field already uses.

4. FieldProps interface duplicated between Text and Number specs. Small test-helper duplication — worth extracting to VueTestHelpers.ts for the next editor that needs the pattern.

Fixes #476

NumberAttributesEditor was missing the validation refinements that
TextAttributesEditor received in PR #551. This adds:

- Error state when minimum exceeds maximum (and vice versa)
- Local input refs with watchers for all fields (minimum, maximum,
  and precision) so in-progress input is preserved even when invalid
- New i18n message `neowiki-property-editor-min-exceeds-max`
- Extracted shared `minExceedsMax` helper used by both Text and Number
  editors
- Moved `FieldProps` test interface to shared `VueTestHelpers`
- CSS classes on min/max fields for robust test selectors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JeroenDeDauw JeroenDeDauw force-pushed the fix/476-polish-number-min-max-ui branch from e30bc32 to fdf4097 Compare April 15, 2026 21:02
@JeroenDeDauw
Copy link
Copy Markdown
Member Author

Should be fixed now

@alistair3149 alistair3149 merged commit c2278b7 into master Apr 16, 2026
12 checks passed
@alistair3149 alistair3149 deleted the fix/476-polish-number-min-max-ui branch April 16, 2026 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Polish min max UI in TextAttributesEditor and NumberAttributesEditor

2 participants