mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 00:03:45 +00:00
test(mobile): scope the IME source guards and drop a circular assertion
Review follow-up on the IME input props.
- Removed an assertion that compared getTerminalImeInputProps' output against
isTerminalAutocorrectEnabled, which the implementation calls internally — it
reduced to `enabled === enabled` and could not fail. The literal expected
objects already cover the mapping.
- The `autoCorrect={false}` guard was file-scoped on a 5387-line route with
non-terminal inputs of its own, so the next unrelated field would have failed
it with a misleading message. Both guards are now scoped to the two terminal
elements via anchored slices, and a missing anchor fails loudly instead of
slicing to EOF and passing vacuously.
- Dropped two negative guards that could never fire: one named an identifier
that no longer exists, the other asserted the exact formatting of a deleted
line.
Settings copy no longer hardcodes the per-platform default that the input
resolves through, and it stops claiming direct input is immune to suggestions —
on Android, clearing NO_SUGGESTIONS is what lets the strip reappear.
This commit is contained in:
@@ -334,9 +334,12 @@ export default function TerminalSettingsScreen() {
|
||||
<Text style={[styles.groupHeading, styles.inputGroupGap]}>KEYBOARD INPUT</Text>
|
||||
<Text style={styles.groupDescription}>
|
||||
Enable phone-style autocomplete, autocorrect, and spelling suggestions in the terminal
|
||||
command bar. {Platform.OS === 'ios' ? 'On' : 'Off'} by default. Direct keyboard input
|
||||
(when keys go straight to the terminal) always sends raw keystrokes, so suggestions
|
||||
don't apply there.
|
||||
command bar.{' '}
|
||||
{isTerminalAutocorrectEnabled('command', Platform.OS, 'unset') ? 'On' : 'Off'} by default.
|
||||
Direct keyboard input (when keys go straight to the terminal) never autocorrects.
|
||||
{Platform.OS === 'android'
|
||||
? ' On Android the keyboard may still offer suggestions you can tap — suppressing them entirely is the same setting that stops Korean and Chinese from composing, so composition wins.'
|
||||
: ''}
|
||||
</Text>
|
||||
<View style={[styles.section, styles.sectionTopGap]}>
|
||||
<View style={styles.row}>
|
||||
|
||||
@@ -64,9 +64,6 @@ describe('getTerminalImeInputProps', () => {
|
||||
for (const preference of PREFERENCES) {
|
||||
const props = getTerminalImeInputProps(entryMode, 'android', preference)
|
||||
expect(props.autoCorrect).not.toBe(false)
|
||||
expect(Object.hasOwn(props, 'autoCorrect')).toBe(
|
||||
isTerminalAutocorrectEnabled(entryMode, 'android', preference)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -101,28 +98,72 @@ describe('getTerminalImeInputProps', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// Why: a slice between anchors silently runs to EOF if an anchor rots, which turns
|
||||
// every assertion below it vacuous — so a missing anchor must fail loudly instead.
|
||||
function sliceBetween(source: string, startAnchor: string, endAnchor: string): string {
|
||||
const start = source.indexOf(startAnchor)
|
||||
expect(start, `start anchor not found: ${startAnchor}`).toBeGreaterThan(-1)
|
||||
const end = source.indexOf(endAnchor, start)
|
||||
expect(end, `end anchor not found after start: ${endAnchor}`).toBeGreaterThan(-1)
|
||||
return source.slice(start, end)
|
||||
}
|
||||
|
||||
describe('session route IME wiring', () => {
|
||||
// Element-scoped, not file-scoped: ~20 other mobile fields legitimately hardcode
|
||||
// autoCorrect={false}, and this route has non-terminal inputs of its own.
|
||||
const liveInput = sliceBetween(
|
||||
sessionRouteSource,
|
||||
'ref={liveInputRef}',
|
||||
'importantForAutofill="no"'
|
||||
)
|
||||
const commandInput = sliceBetween(
|
||||
sessionRouteSource,
|
||||
'ref={commandInputRef}',
|
||||
'onSubmitEditing={() => void handleSend()}'
|
||||
)
|
||||
|
||||
// Guard the call sites: the pure module is only a fix if the route actually uses it.
|
||||
it('routes both terminal inputs through the IME prop builder', () => {
|
||||
expect(sessionRouteSource).toContain(
|
||||
"{...getTerminalImeInputProps('live', Platform.OS, autocompletePref)}"
|
||||
)
|
||||
expect(sessionRouteSource).toContain(
|
||||
"{...getTerminalImeInputProps('command', Platform.OS, autocompletePref)}"
|
||||
expect(liveInput).toContain("getTerminalImeInputProps('live', Platform.OS, autocompletePref)")
|
||||
expect(commandInput).toContain(
|
||||
"getTerminalImeInputProps('command', Platform.OS, autocompletePref)"
|
||||
)
|
||||
})
|
||||
|
||||
it('hardcodes neither autoCorrect nor spellCheck on the terminal inputs', () => {
|
||||
expect(sessionRouteSource).not.toContain('autoCorrect={false}')
|
||||
expect(sessionRouteSource).not.toContain('spellCheck={false}')
|
||||
expect(sessionRouteSource).not.toContain('autoCorrect={autocompleteEnabled}')
|
||||
// #6995: a literal false on either terminal input reintroduces NO_SUGGESTIONS on Android.
|
||||
it('hardcodes neither autoCorrect nor spellCheck on either terminal input', () => {
|
||||
for (const [name, element] of [
|
||||
['live', liveInput],
|
||||
['command', commandInput]
|
||||
] as const) {
|
||||
expect(element, `${name} input`).not.toMatch(/autoCorrect=\{(false|true)\}/)
|
||||
expect(element, `${name} input`).not.toMatch(/spellCheck=\{(false|true)\}/)
|
||||
}
|
||||
})
|
||||
|
||||
// Android caches inputType at mount, so the prop shape and the remount key must flip together.
|
||||
it('keys the Android command-input remount off the same resolved value it emits', () => {
|
||||
expect(commandInput).toContain('commandAutocorrect')
|
||||
expect(sessionRouteSource).toContain(
|
||||
"isTerminalAutocorrectEnabled('command', Platform.OS, autocompletePref)"
|
||||
)
|
||||
})
|
||||
|
||||
// Otherwise the toggle reads "Off" on iOS while the command bar autocorrects (#4606).
|
||||
it('resolves the settings toggle through the same per-platform default', () => {
|
||||
expect(terminalSettingsSource).toContain("isTerminalAutocorrectEnabled('command', Platform.OS,")
|
||||
expect(terminalSettingsSource).not.toContain(
|
||||
'const [autocompleteEnabled, setAutocompleteEnabled] = useState(false)'
|
||||
it('resolves the settings toggle and its copy through the same per-platform default', () => {
|
||||
const autocompleteState = sliceBetween(
|
||||
terminalSettingsSource,
|
||||
'const [autocompleteEnabled, setAutocompleteEnabled]',
|
||||
'const toggleAutocomplete'
|
||||
)
|
||||
// Both the initial value and the post-load value must go through the resolver,
|
||||
// or the row renders a default the command bar does not actually use.
|
||||
expect(autocompleteState).not.toContain('useState(false)')
|
||||
expect(
|
||||
autocompleteState.match(/isTerminalAutocorrectEnabled\('command', Platform\.OS,/g)?.length
|
||||
).toBe(2)
|
||||
// ...and so must the "On/Off by default" sentence in the group description.
|
||||
const groupDescription = sliceBetween(terminalSettingsSource, 'KEYBOARD INPUT', 'by default')
|
||||
expect(groupDescription).toContain("isTerminalAutocorrectEnabled('command', Platform.OS,")
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user