Appium React Native 尚未准备好进行文本输入
Appium React Native Not Ready for Text Input
我最近切换到 Appium + webdriverIO 进行 E2E 测试。除了一个与文本输入相关的测试用例外,一切都运行良好。
基本上,被测组件是一个使用redux-form进行表单管理的登录界面。我不断收到错误 "'"login-field" Other' is not ready for a text input. Neither the accessibility element itself nor its accessible descendants have the input focus"
。组成部分如下:
SignInScreen.tsx
export class SignInScreen extends React.Component<any> {
render() {
const { handleSubmit, submitting, style } = this.props;
return (
<View style={style}>
<View>
<View>
<Field
name="login"
component={Input}
accessibilityLabel="login-field"
testID="login-field"
/>
<Field
secureTextEntry
name="password"
component={Input}
accessibilityLabel="password-field"
testID="password-field"
/>
</View>
</View>
</View>
);
}
}
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View style={{height: 30}}>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
SignInScreen.test.ts
describe('Sign In Screen Test', () => {
let client;
beforeAll(async () => {
// set up code
});
afterAll(async () => {
// tear down code
});
it('Can login', async () => {
const loginField = await client.$('~login-field');
await loginField.setValue('test@gmail.com'); // error here
const passwordField = await client.$('~password-field');
await passwordField.set('password' + '\n');
});
});
我确实意识到,当我在 Input.tsx
组件中的现有 <TextInput />
组件之上添加一个额外的 <TextInput />
时,测试用例会起作用,如下所示:
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput />
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View style={{height: 30}}>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
或者我把嵌套错误信息的View
组件中的固定高度去掉如下:
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
那么是什么原因呢?我真的不知道是什么导致 Appium 在不进行上述调整的情况下无法获取输入焦点。
我相信这是 Appium 最近的一个错误 - https://github.com/appium/java-client/issues/1386
您不应该为 ios 指定 accessibilityLabel 单独的道具 ios 和 android 尝试下一个解决方法:
export default function testID(id) {
return Platform.OS === 'android'
? {
accessible : true,
accessibilityLabel: id,
}
: {
testID: id,
};
}
然后
<TextInput
{...otherProps}
{...testID('some-testID')}
/>
我最近切换到 Appium + webdriverIO 进行 E2E 测试。除了一个与文本输入相关的测试用例外,一切都运行良好。
基本上,被测组件是一个使用redux-form进行表单管理的登录界面。我不断收到错误 "'"login-field" Other' is not ready for a text input. Neither the accessibility element itself nor its accessible descendants have the input focus"
。组成部分如下:
SignInScreen.tsx
export class SignInScreen extends React.Component<any> {
render() {
const { handleSubmit, submitting, style } = this.props;
return (
<View style={style}>
<View>
<View>
<Field
name="login"
component={Input}
accessibilityLabel="login-field"
testID="login-field"
/>
<Field
secureTextEntry
name="password"
component={Input}
accessibilityLabel="password-field"
testID="password-field"
/>
</View>
</View>
</View>
);
}
}
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View style={{height: 30}}>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
SignInScreen.test.ts
describe('Sign In Screen Test', () => {
let client;
beforeAll(async () => {
// set up code
});
afterAll(async () => {
// tear down code
});
it('Can login', async () => {
const loginField = await client.$('~login-field');
await loginField.setValue('test@gmail.com'); // error here
const passwordField = await client.$('~password-field');
await passwordField.set('password' + '\n');
});
});
我确实意识到,当我在 Input.tsx
组件中的现有 <TextInput />
组件之上添加一个额外的 <TextInput />
时,测试用例会起作用,如下所示:
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput />
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View style={{height: 30}}>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
或者我把嵌套错误信息的View
组件中的固定高度去掉如下:
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
那么是什么原因呢?我真的不知道是什么导致 Appium 在不进行上述调整的情况下无法获取输入焦点。
我相信这是 Appium 最近的一个错误 - https://github.com/appium/java-client/issues/1386
您不应该为 ios 指定 accessibilityLabel 单独的道具 ios 和 android 尝试下一个解决方法:
export default function testID(id) {
return Platform.OS === 'android'
? {
accessible : true,
accessibilityLabel: id,
}
: {
testID: id,
};
}
然后
<TextInput
{...otherProps}
{...testID('some-testID')}
/>