diff --git a/change/react-native-windows-bc55b824-3ab8-4b55-9cd6-316450f7f562.json b/change/react-native-windows-bc55b824-3ab8-4b55-9cd6-316450f7f562.json new file mode 100644 index 00000000000..35a70bf4fcf --- /dev/null +++ b/change/react-native-windows-bc55b824-3ab8-4b55-9cd6-316450f7f562.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Implement selectTextOnFocus for TextInput in Fabric", + "packageName": "react-native-windows", + "email": "14967941+danielayala94@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js b/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js index 68dcad3ba41..e93af10d113 100644 --- a/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js @@ -208,6 +208,30 @@ const examples: Array = [ ); }, }, + { + title: 'Select text on focus', + render: function (): React.Node { + return ( + + Select text on focus: + + + Do not select text on focus if clear text on focus is enabled: + + + + ); + }, + }, { title: 'Colors and text inputs', render: function (): React.Node { diff --git a/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts b/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts index 7e901d3dcb3..2019926448b 100644 --- a/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts +++ b/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts @@ -462,6 +462,62 @@ describe('TextInput Tests', () => { // Verify the textInput contents are cleared after regaining focus expect(await componentFocusTrue.getText()).toBe(''); }); + + test('TextInputs can select text on focus', async () => { + const component = await app.findElementByTestID('select-text-on-focus'); + await component.waitForDisplayed({timeout: 5000}); + + await app.waitUntil( + async () => { + await component.setValue('Hello World'); + return (await component.getText()) === 'Hello World'; + }, + { + interval: 1500, + timeout: 5000, + timeoutMsg: `Unable to enter correct text.`, + }, + ); + + // Check if the text is selected on focus. + await component.click(); + + const dump = await dumpVisualTree('select-text-on-focus'); + expect(dump).toMatchSnapshot(); + }); + + test('TextInputs can clear text on focus even if selectTextOnFocus == true', async () => { + const targetComponent = await app.findElementByTestID( + 'select-text-on-focus-while-clear-text-on-focus', + ); + await targetComponent.waitForDisplayed({timeout: 5000}); + + await app.waitUntil( + async () => { + await targetComponent.setValue('Hello World'); + return (await targetComponent.getText()) === 'Hello World'; + }, + { + interval: 1500, + timeout: 5000, + timeoutMsg: `Unable to enter correct text.`, + }, + ); + + // Click on the previous textInput to move focus away from this TextInput + const anotherTextInput = await app.findElementByTestID( + 'select-text-on-focus', + ); + await anotherTextInput.waitForDisplayed({timeout: 5000}); + await anotherTextInput.click(); + + // Now click on the tested component, make sure the text is cleared. + await targetComponent.click(); + + // Verify the textInput contents are cleared after regaining focus + expect(await targetComponent.getText()).toBe(''); + }); + test('TextInputs can have inline images', async () => { const component = await app.findElementByTestID('textinput-inline-images'); await component.waitForDisplayed({timeout: 5000}); diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap index aaa4e2766d9..bc78cfc3890 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap @@ -333,7 +333,7 @@ exports[`TextInput Tests Text have cursorColor 1`] = ` "Visual Tree": { "Comment": "textinput-cursorColor", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -561,7 +561,7 @@ exports[`TextInput Tests TextInputs can autocomplete, address country 1`] = ` "Visual Tree": { "Comment": "textinput-autocomplete-address-country", "Offset": "0, 0, 0", - "Size": "916, 29", + "Size": "916, 28", "Visual Type": "SpriteVisual", "__Children": [ { @@ -717,7 +717,7 @@ exports[`TextInput Tests TextInputs can autocomplete, one-time-code 1`] = ` "Visual Tree": { "Comment": "textinput-autocomplete-one-time-code", "Offset": "0, 0, 0", - "Size": "916, 28", + "Size": "916, 29", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1002,12 +1002,12 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "__Children": [ { "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1217,7 +1217,7 @@ exports[`TextInput Tests TextInputs can be editable 1`] = ` "Visual Tree": { "Comment": "textinput-editable", "Offset": "0, 0, 0", - "Size": "916, 29", + "Size": "916, 28", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1527,7 +1527,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 1`] = ` "Visual Tree": { "Comment": "textinput-not-editable", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1605,7 +1605,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 2 1`] = ` "Visual Tree": { "Comment": "textinput-not-editable2", "Offset": "0, 0, 0", - "Size": "916, 28", + "Size": "916, 29", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1680,7 +1680,7 @@ exports[`TextInput Tests TextInputs can clear on submit 1`] = ` "Visual Tree": { "Comment": "textinput-clear-on-submit", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1830,7 +1830,7 @@ exports[`TextInput Tests TextInputs can clear on submit with custom submit key e "Visual Tree": { "Comment": "textinput-clear-on-submit-2", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1905,7 +1905,7 @@ exports[`TextInput Tests TextInputs can customize its padding 1`] = ` "Visual Tree": { "Comment": "textinput-padding", "Offset": "0, 0, 0", - "Size": "916, 28", + "Size": "916, 29", "Visual Type": "SpriteVisual", "__Children": [ { @@ -2601,7 +2601,7 @@ exports[`TextInput Tests TextInputs can have caretHidden 1`] = ` "Visual Tree": { "Comment": "textinput-carethidden", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -2679,7 +2679,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, Compile 1` "Visual Tree": { "Comment": "textinput-return-Compile", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -2757,7 +2757,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, React Nati "Visual Tree": { "Comment": "textinput-return-React Native", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -2835,7 +2835,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, done 1`] = "Visual Tree": { "Comment": "textinput-return-done", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -2913,7 +2913,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, go 1`] = ` "Visual Tree": { "Comment": "textinput-return-go", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3069,7 +3069,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, none 1`] = "Visual Tree": { "Comment": "textinput-return-none", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3147,7 +3147,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, previous 1` "Visual Tree": { "Comment": "textinput-return-previous", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3381,7 +3381,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=-1 "Visual Tree": { "Comment": "textinput-letterspacing--1", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3459,7 +3459,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=0 "Visual Tree": { "Comment": "textinput-letterspacing-0", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3615,7 +3615,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=9 "Visual Tree": { "Comment": "textinput-letterspacing-9", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -4023,7 +4023,7 @@ exports[`TextInput Tests TextInputs can have inline images, drawable props not s "Visual Tree": { "Comment": "textinput-inline-images-3", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -4179,7 +4179,7 @@ exports[`TextInput Tests TextInputs can have shadows 1`] = ` "Visual Tree": { "Comment": "textinput-shadow", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -4772,6 +4772,83 @@ exports[`TextInput Tests TextInputs can rewrite characters: Replace Space with U } `; +exports[`TextInput Tests TextInputs can select text on focus 1`] = ` +{ + "Automation Tree": { + "AutomationId": "select-text-on-focus", + "ControlType": 50004, + "IsKeyboardFocusable": true, + "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Hello World", + "ValuePattern.Value": "Hello World", + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", + "_Props": { + "TestId": "select-text-on-focus", + }, + }, + "Visual Tree": { + "Comment": "select-text-on-focus", + "Offset": "0, 0, 0", + "Size": "916, 32", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "1, 0, 0", + "Size": "-2, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-1, 0, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-1, 1, 0", + "Size": "1, -2", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-1, -1, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "1, -1, 0", + "Size": "-2, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -1, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 1, 0", + "Size": "1, -2", + "Visual Type": "SpriteVisual", + }, + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 255)", + }, + "Offset": "83, 5, 0", + "Opacity": 0, + "Size": "1, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, +} +`; + exports[`TextInput Tests TextInputs can set their readOnly prop to false 1`] = ` { "Automation Tree": { @@ -4870,7 +4947,7 @@ exports[`TextInput Tests TextInputs can set their readOnly prop to true 1`] = ` "Visual Tree": { "Comment": "textinput-readyonly", "Offset": "0, 0, 0", - "Size": "916, 29", + "Size": "916, 28", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5099,7 +5176,7 @@ exports[`TextInput Tests TextInputs have a custom highlight color 1`] = ` "Visual Tree": { "Comment": "textinput-custom-highlight-color", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5177,7 +5254,7 @@ exports[`TextInput Tests TextInputs have a custom placeholder text color 1`] = ` "Visual Tree": { "Comment": "textinput-custom-placeholder-color", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5254,7 +5331,7 @@ exports[`TextInput Tests TextInputs have a custom text color 1`] = ` "Visual Tree": { "Comment": "textinput-custom-color", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5487,7 +5564,7 @@ exports[`TextInput Tests TextInputs have a default text color 1`] = ` "Visual Tree": { "Comment": "textinput-default-color", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5565,7 +5642,7 @@ exports[`TextInput Tests TextInputs have a default underline color 1`] = ` "Visual Tree": { "Comment": "textinput-default-underline-color", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5815,12 +5892,12 @@ exports[`TextInput Tests TextInputs which have a searchbox role should also supp "__Children": [ { "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap index f1aa6dc8172..0e9c53c8acf 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap @@ -751,7 +751,6 @@ exports[`snapshotAllPages Accessibility Windows 4`] = ` The following View exposes the accessibilityValue.Text field + + Select text on focus: + + + + Do not select text on focus if clear text on focus is enabled: + + + +`; + +exports[`snapshotAllPages TextInput 24`] = ` `; -exports[`snapshotAllPages TextInput 24`] = ` +exports[`snapshotAllPages TextInput 25`] = ` `; -exports[`snapshotAllPages TextInput 25`] = ` +exports[`snapshotAllPages TextInput 26`] = ` `; -exports[`snapshotAllPages TextInput 26`] = ` +exports[`snapshotAllPages TextInput 27`] = ` `; -exports[`snapshotAllPages TextInput 27`] = ` +exports[`snapshotAllPages TextInput 28`] = ` `; -exports[`snapshotAllPages TextInput 28`] = ` +exports[`snapshotAllPages TextInput 29`] = ` `; -exports[`snapshotAllPages TextInput 29`] = ` +exports[`snapshotAllPages TextInput 30`] = ` `; -exports[`snapshotAllPages TextInput 30`] = ` +exports[`snapshotAllPages TextInput 31`] = ` `; -exports[`snapshotAllPages TextInput 31`] = ` +exports[`snapshotAllPages TextInput 32`] = ` `; -exports[`snapshotAllPages TextInput 32`] = ` +exports[`snapshotAllPages TextInput 33`] = ` `; -exports[`snapshotAllPages TextInput 33`] = ` +exports[`snapshotAllPages TextInput 34`] = ` `; -exports[`snapshotAllPages TextInput 34`] = ` +exports[`snapshotAllPages TextInput 35`] = ` `; -exports[`snapshotAllPages TextInput 35`] = ` +exports[`snapshotAllPages TextInput 36`] = ` `; -exports[`snapshotAllPages TextInput 36`] = ` +exports[`snapshotAllPages TextInput 37`] = ` `; -exports[`snapshotAllPages TextInput 37`] = ` +exports[`snapshotAllPages TextInput 38`] = ` PressIn/PressOut message @@ -79562,7 +79620,7 @@ exports[`snapshotAllPages TextInput 37`] = ` `; -exports[`snapshotAllPages TextInput 38`] = ` +exports[`snapshotAllPages TextInput 39`] = ` Default submit key (Enter): @@ -79698,7 +79756,7 @@ exports[`snapshotAllPages TextInput 38`] = ` `; -exports[`snapshotAllPages TextInput 39`] = ` +exports[`snapshotAllPages TextInput 40`] = ` [ Spell Check Enabled: @@ -79813,7 +79871,7 @@ exports[`snapshotAllPages TextInput 40`] = ` ] `; -exports[`snapshotAllPages TextInput 41`] = ` +exports[`snapshotAllPages TextInput 42`] = ` CaretHidden @@ -79845,7 +79903,7 @@ exports[`snapshotAllPages TextInput 41`] = ` `; -exports[`snapshotAllPages TextInput 42`] = ` +exports[`snapshotAllPages TextInput 43`] = ` Cursorcolor @@ -79877,7 +79935,7 @@ exports[`snapshotAllPages TextInput 42`] = ` `; -exports[`snapshotAllPages TextInput 43`] = ` +exports[`snapshotAllPages TextInput 44`] = ` Shadow @@ -79915,7 +79973,7 @@ exports[`snapshotAllPages TextInput 43`] = ` `; -exports[`snapshotAllPages TextInput 44`] = ` +exports[`snapshotAllPages TextInput 45`] = ` `; -exports[`snapshotAllPages TextInput 45`] = ` +exports[`snapshotAllPages TextInput 46`] = ` { clearTextOnFocus={true} placeholder={'Clear text on focus'} /> + +