我正在使用Detox,并使用以下UI对tipsi-stripe软件包进行集成测试:
我的测试如下:
...
await expect(element(by.text('10'))).toBeVisible()
await expect(element(by.text('Give $10'))).toBeNotVisible()
await element(by.text('10')).tap()
await expect(element(by.text('Give $10'))).toBeVisible()
await expect(element(by.id('cc-card-input'))).toBeVisible()
await element(by.id('cc-card-input')).typeText("4242424242424242")
...
最后一行失败:
● Signin › allows the person to make a payment
Error performing 'Click to focus & type text (4242424242424242)' on view '(with tag value: is "cc-card-input" and view has effective visibility=VISIBLE)'.
> 28 | await element(by.id('cc-card input')).typeText("4242424242424242")
失败表明无法输入cc卡输入。
从相关库中获取组件:
import React, { Component } from 'react'
import {
requireNativeComponent,
findNodeHandle,
StyleSheet,
View,
TouchableWithoutFeedback,
ViewPropTypes,
Platform,
Text,
} from 'react-native'
import PropTypes from 'prop-types'
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState'
const FieldStylePropType = PropTypes.shape({
...ViewPropTypes.style,
color: PropTypes.string,
})
/**
* @typedef {Object} PaymentCardTextFieldNativeEventParams
* @property {string} number -- card number as a string
* @property {number} expMonth
* @property {number} expYear
* @property {string} cvc
*/
/**
* @typedef {Object} PaymentCardTextFieldNativeEvent
* @property {boolean} valid
* @property {PaymentCardTextFieldNativeEventParams} params
*/
/**
* @callback OnChangeCallback
* @param {PaymentCardTextFieldNativeEvent} params
*/
/**
* // TODO: Get a more precise type here, not sure how to JSDoc react-native Style Types
* @typedef {Object} PaymentComponentTextFieldStyleProp
*/
/**
* A Component that collects the CardNumber, ExpirationDate, and CVC all in one.
* @typedef {Object} PaymentCardTextFieldProps
*
* @property {string} expirationPlaceholder
* @property {string} numberPlaceholder
* @property {string} cvcPlaceholder
* @property {boolean} disabled
* @property {OnChangeCallback} onChange
* @property {PaymentComponentTextFieldStyleProp} style
*
* @property {string} cursorColor iOS-only!
* @property {string} textErrorColor iOS-only!
* @property {string} placeholderColor iOS-only!
* @property {"default"|"light"|"dark"} keyboardAppearance iOS-only!
*
* @property {boolean} setEnabled Android-only!
* @property {string} backgroundColor Android-only!
* @property {string} cardNumber Android-only!
* @property {string} expDate Android-only!
* @property {string} securityCode Android-only!
*/
const NativePaymentCardTextField = requireNativeComponent('TPSCardField', PaymentCardTextField, {
nativeOnly: {
borderColor: true,
borderWidth: true,
cornerRadius: true,
textColor: true,
fontFamily: true,
fontWeight: true,
fontStyle: true,
fontSize: true,
enabled: true,
onChange: true,
params: true, // Currently iOS only
keyboardAppearance: true, // iOS only
},
})
/**
* @type {import('react').ComponentClass<PaymentCardTextFieldProps>}
*/
export default class PaymentCardTextField extends Component {
static propTypes = {
...ViewPropTypes,
style: FieldStylePropType,
// Common
expirationPlaceholder: PropTypes.string,
numberPlaceholder: PropTypes.string,
cvcPlaceholder: PropTypes.string,
disabled: PropTypes.bool,
onChange: PropTypes.func,
...Platform.select({
ios: {
cursorColor: PropTypes.string,
textErrorColor: PropTypes.string,
placeholderColor: PropTypes.string,
keyboardAppearance: PropTypes.oneOf(['default', 'light', 'dark']),
},
android: {
setEnabled: PropTypes.bool,
backgroundColor: PropTypes.string,
cardNumber: PropTypes.string,
expDate: PropTypes.string,
securityCode: PropTypes.string,
},
}),
}
static defaultProps = {
...View.defaultProps,
}
valid = false // eslint-disable-line react/sort-comp
params = {
number: '',
expMonth: 0,
expYear: 0,
cvc: '',
}
componentWillUnmount() {
if (this.isFocused()) {
this.blur()
}
}
isFocused = () => TextInputState.currentlyFocusedField() === findNodeHandle(this.cardTextFieldRef)
focus = () => {
TextInputState.focusTextInput(findNodeHandle(this.cardTextFieldRef))
}
blur = () => {
TextInputState.blurTextInput(findNodeHandle(this.cardTextFieldRef))
}
handlePress = () => {
this.focus()
}
handleChange = (event) => {
const { onChange, onParamsChange } = this.props
const { nativeEvent } = event
this.valid = nativeEvent.valid
this.params = nativeEvent.params
if (onChange) {
// Send the intended parameters back into JS
onChange({ ...nativeEvent })
}
if (onParamsChange) {
onParamsChange(nativeEvent.valid, nativeEvent.params)
}
}
setCardTextFieldRef = (node) => {
this.cardTextFieldRef = node
}
// Previously on iOS only
setParams = (params) => {
this.cardTextFieldRef.setNativeProps({ params })
}
render() {
const {
style,
disabled,
expDate,
cardNumber,
securityCode,
cursorColor,
textErrorColor,
placeholderColor,
numberPlaceholder,
expirationPlaceholder,
cvcPlaceholder,
keyboardAppearance,
...rest
} = this.props
const {
borderColor,
borderWidth,
borderRadius,
fontFamily,
fontWeight,
fontStyle,
fontSize,
overflow,
backgroundColor,
color,
...fieldStyles
} = StyleSheet.flatten(style)
const viewStyles = {
overflow,
width: fieldStyles.width,
}
const commonStyles = {
borderColor,
borderWidth,
borderRadius,
backgroundColor,
}
return (
<View style={[commonStyles, viewStyles]}>
<TouchableWithoutFeedback
style={{ borderWidth: 2, borderColor: 'red'}}
rejectResponderTermination
testID={rest.testID}
onPress={this.handlePress}
accessible={rest.accessible}
accessibilityLabel={rest.accessibilityLabel}
accessibilityTraits={rest.accessibilityTraits}
>
<NativePaymentCardTextField
ref={this.setCardTextFieldRef}
style={[styles.field, fieldStyles]}
borderColor="transparent"
borderWidth={0}
cornerRadius={borderRadius}
textColor={color}
fontFamily={fontFamily}
fontWeight={fontWeight}
fontStyle={fontStyle}
fontSize={fontSize}
enabled={!disabled}
numberPlaceholder={numberPlaceholder}
expirationPlaceholder={expirationPlaceholder}
cvcPlaceholder={cvcPlaceholder}
onChange={this.handleChange}
// iOS only
cursorColor={cursorColor}
textErrorColor={textErrorColor}
placeholderColor={placeholderColor}
keyboardAppearance={keyboardAppearance}
// Android only
cardNumber={cardNumber}
expDate={expDate}
securityCode={securityCode}
/>
</TouchableWithoutFeedback>
</View>
)
}
}
您会看到testID被分配给TouchableWithoutFeedBack组件-而不是输入的组件。
我尝试过
NativePaymentCardTextField
上设置testID accessible={true}
,并在父组件上设置了accessibilityId 我在两者上都遇到相同的错误。
要在此组件中输入信用卡号(如果可能的话),我需要做些什么
谢谢。
答案 0 :(得分:0)
从层次结构来看,似乎cc-card-input
测试ID被分配给包装器而不是文本字段本身。特别是,本节显示:
+----------->CreditCardForm{id=243, visibility=VISIBLE, width=787, height=115, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.view.ViewGroup$LayoutParams@ad170a6, tag=cc-card-input, root-is-layout-requested=false, has-input-connection=false, x=3.0, y=3.0, child-count=2}
|
+------------>LinearLayout{id=2131296373, res-name=cc_form_layout, visibility=VISIBLE, width=703, height=69, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.RelativeLayout$LayoutParams@ce0b53d, tag=null, root-is-layout-requested=false, has-input-connection=false, x=42.0, y=21.0, child-count=2}
|
+------------->FrameLayout{id=-1, visibility=VISIBLE, width=94, height=53, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@5c61800, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=8.0, child-count=2}
|
+-------------->ImageView{id=-1, visibility=VISIBLE, width=84, height=53, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@a86839, tag=null, root-is-layout-requested=false, has-input-connection=false, x=10.0, y=0.0}
|
+-------------->ImageView{id=-1, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@c8bee7e, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+------------->CreditCardEntry{id=2131296370, res-name=cc_entry, visibility=VISIBLE, width=609, height=69, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@e74b42c, tag=null, root-is-layout-requested=false, has-input-connection=false, x=94.0, y=0.0, child-count=1}
|
+-------------->LinearLayout{id=2131296371, res-name=cc_entry_internal, visibility=VISIBLE, width=1632, height=63, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@1f4748a, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=4}
|
+--------------->CreditCardText{id=2131296368, res-name=cc_card, visibility=VISIBLE, width=1080, height=63, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@d53dafb, tag=null, root-is-layout-requested=false, has-input-connection=true, editor-info=[inputType=0x2 imeOptions=0x10000006 privateImeOptions=null actionLabel=null actionId=0 initialSelStart=0 initialSelEnd=0 initialCapsMode=0x0 hintText=1234 5678 9012 3456 label=null packageName=null fieldId=0 fieldName=null extras=null ], x=0.0, y=0.0, text=, hint=1234 5678 9012 3456, input-type=2, ime-target=true, has-links=false}
|
+--------------->TextView{id=2131296374, res-name=cc_four_digits, visibility=VISIBLE, width=104, height=63, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@28ee718, tag=null, root-is-layout-requested=false, has-input-connection=false, x=1080.0, y=0.0, text=4242, input-type=0, ime-target=false, has-links=false}
(查看与CreditCardForm
视图关联的标签)
在确实可见的情况下,您只能有效typeText()
覆盖作为文本输入的视图(即,打开软键盘的位置)。
将测试ID重新定位到可以有效接受输入的视图即可解决它(我很难说哪个是根据层次结构确定的确切视图,因为视图似乎是自定义的。)