@@ -12,6 +12,7 @@ import { encapsulatedAction } from '../../framework/encapsulatedAction';
1212import PlaywrightMatchers from '../../framework/PlaywrightMatchers' ;
1313import { PlatformDetector } from '../../framework/PlatformLocator' ;
1414import { getDriver } from '../../framework/PlaywrightUtilities' ;
15+ import { ImportSRPIDs } from '../../../app/components/Views/ImportNewSecretRecoveryPhrase/SRPImport.testIds' ;
1516
1617class ImportWalletView {
1718 get container ( ) : DetoxElement {
@@ -52,6 +53,14 @@ class ImportWalletView {
5253 ) ;
5354 }
5455
56+ /**
57+ * Returns the encapsulated element for the SRP input field at the given word index.
58+ *
59+ * iOS label convention: the first field (index 0) has no label filter;
60+ * subsequent fields use 1-indexed labels offset by one from the word index
61+ * (word 1 → label "2.", word 2 → label "3.", etc.).
62+ * This matches the native iOS SRP form where the first labeled field is "2.".
63+ */
5564 seedPhraseInput ( index : number ) : EncapsulatedElementType {
5665 return encapsulated ( {
5766 detox : ( ) =>
@@ -72,7 +81,7 @@ class ImportWalletView {
7281 ios : ( ) =>
7382 PlaywrightMatchers . getElementByXPath (
7483 index !== 0
75- ? `//XCUIElementTypeOther[@name="textfield" and @label="${ index } ."]`
84+ ? `//XCUIElementTypeOther[@name="textfield" and @label="${ index + 1 } ."]`
7685 : '//XCUIElementTypeOther[@name="textfield"]' ,
7786 ) ,
7887 } ,
@@ -161,14 +170,42 @@ class ImportWalletView {
161170 } ) ;
162171 }
163172
173+ /**
174+ * Returns the input element for the given SRP index
175+ * @param srpIndex - The index of the SRP word
176+ * @param onboarding - Whether the screen is onboarding or not
177+ * @returns The input element for the given SRP index
178+ */
179+ async inputOfIndex (
180+ srpIndex : number ,
181+ onboarding : boolean = true ,
182+ ) : Promise < string > {
183+ if ( onboarding ) {
184+ if ( await PlatformDetector . isAndroid ( ) ) {
185+ return `${ ImportFromSeedSelectorsIDs . SEED_PHRASE_INPUT_ID } _${ srpIndex } ` ;
186+ }
187+ return `//XCUIElementTypeOther[@name="textfield" and @label="${ srpIndex } ."]` ;
188+
189+ }
190+ if ( await PlatformDetector . isAndroid ( ) ) {
191+ return `seed-phrase-input_${ srpIndex } ` ;
192+ }
193+ return `//*[@label="${ srpIndex + 1 } ."]` ;
194+
195+
196+ }
197+
164198 /**
165199 * Types a secret recovery phrase word-by-word into the SRP input fields.
166- * Handles platform-specific field indexing:
167- * - Android: fields indexed from 0 (seed-phrase-input-id_0, _1, ...)
168- * - iOS: fields indexed from 1 via XPath labels ("1.", "2.", ...)
200+ * Uses seedPhraseInput(i) for consistent selector resolution across platforms.
201+ *
202+ * Onboarding flow matches wdio ImportFromSeedScreen.typeSecretRecoveryPhrase:
203+ * - First word typed with trailing space into field 0
204+ * - Middle words typed with trailing space + tap into fields 1..n-2
205+ * - Last word typed WITHOUT trailing space into field n-1
206+ *
169207 * @param phrase - The secret recovery phrase to type
170208 * @param onboarding - Whether the screen is onboarding or not
171- * @returns void
172209 */
173210 async typeSecretRecoveryPhrase (
174211 phrase : string ,
@@ -180,47 +217,42 @@ class ImportWalletView {
180217 const isAndroid = await PlatformDetector . isAndroid ( ) ;
181218
182219 if ( onboarding ) {
183- // Type first word into the first field
220+ // Type first word into the first field (with trailing space)
184221 const firstField = await asPlaywrightElement ( this . seedPhraseInput ( 0 ) ) ;
185222 await firstField . type ( `${ phraseArray [ 0 ] } ` ) ;
186223
187- // Type remaining words into indexed fields
188- for ( let i = 1 ; i < phraseArray . length ; i ++ ) {
189- const fieldIndex = isAndroid ? i : i + 1 ;
190- let input ;
191- if ( isAndroid ) {
192- input = await PlaywrightMatchers . getElementById (
193- `${ ImportFromSeedSelectorsIDs . SEED_PHRASE_INPUT_ID } _${ fieldIndex } ` ,
194- ) ;
195- } else {
196- input = await PlaywrightMatchers . getElementByXPath (
197- `//XCUIElementTypeOther[@name="textfield" and @label="${ fieldIndex } ."]` ,
198- ) ;
199- }
224+ // Type middle words (with trailing space + tap)
225+ for ( let i = 1 ; i < phraseArray . length - 1 ; i ++ ) {
226+ const input = await asPlaywrightElement ( this . seedPhraseInput ( i ) ) ;
200227 await input . type ( `${ phraseArray [ i ] } ` ) ;
201228 await input . click ( ) ;
202229 }
230+
231+ // Type last word (without trailing space, no tap)
232+ const lastIndex = phraseArray . length - 1 ;
233+ const lastInput = await asPlaywrightElement (
234+ this . seedPhraseInput ( lastIndex ) ,
235+ ) ;
236+ await lastInput . type ( phraseArray [ lastIndex ] ) ;
203237 } else {
204238 // Non-onboarding flow (adding additional SRP)
205239 let firstInput ;
206240 if ( isAndroid ) {
207- firstInput =
208- await PlaywrightMatchers . getElementById ( 'seed-phrase-input' ) ;
241+ firstInput = await PlaywrightMatchers . getElementById (
242+ ImportSRPIDs . SEED_PHRASE_INPUT_ID ,
243+ ) ;
209244 } else {
210245 firstInput = await PlaywrightMatchers . getElementById ( 'textfield' ) ;
211246 }
212247 await firstInput . type ( `${ phraseArray [ 0 ] } ` ) ;
213248
214249 for ( let i = 1 ; i < phraseArray . length ; i ++ ) {
250+ const fieldId = await this . inputOfIndex ( i , false ) ;
215251 let input ;
216252 if ( isAndroid ) {
217- input = await PlaywrightMatchers . getElementById (
218- `seed-phrase-input_${ i } ` ,
219- ) ;
253+ input = await PlaywrightMatchers . getElementById ( fieldId ) ;
220254 } else {
221- input = await PlaywrightMatchers . getElementByXPath (
222- `//*[@label="${ i + 1 } ."]` ,
223- ) ;
255+ input = await PlaywrightMatchers . getElementByXPath ( fieldId ) ;
224256 }
225257 await input . type ( `${ phraseArray [ i ] } ` ) ;
226258 await input . click ( ) ;
0 commit comments