From 073bdbdc68b4f35a919892c495cd7d48c0c873ec Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Jun 2025 09:09:45 +0000
Subject: [PATCH 1/5] Initial plan for issue
From af5d124a89925c199e69810e860e3cc00ce795f1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Jun 2025 09:18:34 +0000
Subject: [PATCH 2/5] Add dynamic Button examples and functional tests for fast
refresh
Co-authored-by: anupriya13 <54227869+anupriya13@users.noreply.github.com>
---
.../js/examples/Button/ButtonExample.js | 135 ++++++++++++++++++
.../test/ButtonComponentTest.test.ts | 89 ++++++++++++
2 files changed, 224 insertions(+)
diff --git a/packages/@react-native/tester/js/examples/Button/ButtonExample.js b/packages/@react-native/tester/js/examples/Button/ButtonExample.js
index 332f9cd6669..60f388eb208 100644
--- a/packages/@react-native/tester/js/examples/Button/ButtonExample.js
+++ b/packages/@react-native/tester/js/examples/Button/ButtonExample.js
@@ -221,11 +221,146 @@ exports.examples = [
);
},
},
+ {
+ title: 'Button with dynamic text',
+ description: 'Button text updates when pressed',
+ render: function (): React.Node {
+ return ;
+ },
+ },
+ {
+ title: 'Button with dynamic color',
+ description: 'Button color updates when pressed',
+ render: function (): React.Node {
+ return ;
+ },
+ },
+ {
+ title: 'Button with dynamic disabled state',
+ description: 'Button disabled state toggles when pressed',
+ render: function (): React.Node {
+ return ;
+ },
+ },
+ {
+ title: 'Button with dynamic styling on press',
+ description: 'Button updates styling when pressed',
+ render: function (): React.Node {
+ return ;
+ },
+ },
];
+// Dynamic Button Components for fast refresh testing
+function DynamicTextButton(): React.Node {
+ const [buttonText, setButtonText] = React.useState('Initial Text');
+ const [pressCount, setPressCount] = React.useState(0);
+
+ const onPress = () => {
+ const newCount = pressCount + 1;
+ setPressCount(newCount);
+ setButtonText(`Pressed ${newCount} times`);
+ };
+
+ return (
+
+ );
+}
+
+function DynamicColorButton(): React.Node {
+ const [colorIndex, setColorIndex] = React.useState(0);
+ const colors = ['#007AFF', '#FF3B30', '#34C759', '#FF9500', '#5856D6'];
+
+ const onPress = () => {
+ setColorIndex((prev) => (prev + 1) % colors.length);
+ };
+
+ return (
+
+ {theme => (
+
+ )}
+
+ );
+}
+
+function DynamicDisabledButton(): React.Node {
+ const [isDisabled, setIsDisabled] = React.useState(false);
+ const [toggleText, setToggleText] = React.useState('Disable Me');
+
+ const onPress = () => {
+ if (!isDisabled) {
+ setIsDisabled(true);
+ setToggleText('Disabled');
+ // Re-enable after 2 seconds for testing
+ setTimeout(() => {
+ setIsDisabled(false);
+ setToggleText('Disable Me');
+ }, 2000);
+ }
+ };
+
+ return (
+
+ );
+}
+
+function DynamicStyleButton(): React.Node {
+ const [isPressed, setIsPressed] = React.useState(false);
+ const [pressCount, setPressCount] = React.useState(0);
+
+ const onPress = () => {
+ setIsPressed(true);
+ setPressCount(prev => prev + 1);
+ // Reset pressed state after visual feedback
+ setTimeout(() => setIsPressed(false), 300);
+ };
+
+ return (
+
+ {theme => (
+
+
+
+ )}
+
+ );
+}
+
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'space-between',
},
+ dynamicContainer: {
+ padding: 10,
+ borderRadius: 5,
+ backgroundColor: 'transparent',
+ },
+ pressedContainer: {
+ backgroundColor: '#f0f0f0',
+ },
});
diff --git a/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts b/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts
index f7b85df5c53..dc45b52ba8f 100644
--- a/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts
+++ b/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts
@@ -138,4 +138,93 @@ describe('Button Tests', () => {
const dump3 = await dumpVisualTree('accessible_focusable_false_button');
expect(dump3).toMatchSnapshot();
});
+
+ // Functional tests for dynamic button behaviors
+ test('Button text should update on fast refresh', async () => {
+ await searchBox('dynamic text');
+ const component = await app.findElementByTestID('dynamic_text_button');
+ await component.waitForDisplayed({timeout: 5000});
+
+ // Get initial state
+ const initialDump = await dumpVisualTree('dynamic_text_button');
+ expect(initialDump).toMatchSnapshot('initial-text');
+
+ // Click to change text
+ await component.click();
+
+ // Verify text updated
+ const updatedDump = await dumpVisualTree('dynamic_text_button');
+ expect(updatedDump).toMatchSnapshot('updated-text');
+ expect(updatedDump.Text).toContain('Pressed 1 times');
+ });
+
+ test('Button color should update on fast refresh', async () => {
+ await searchBox('dynamic color');
+ const component = await app.findElementByTestID('dynamic_color_button');
+ await component.waitForDisplayed({timeout: 5000});
+
+ // Get initial state
+ const initialDump = await dumpVisualTree('dynamic_color_button');
+ expect(initialDump).toMatchSnapshot('initial-color');
+
+ // Click to change color
+ await component.click();
+
+ // Verify color updated (visual tree should show different styling)
+ const updatedDump = await dumpVisualTree('dynamic_color_button');
+ expect(updatedDump).toMatchSnapshot('updated-color');
+ });
+
+ test('Button disabled status should update on fast refresh', async () => {
+ await searchBox('dynamic disabled');
+ const component = await app.findElementByTestID('dynamic_disabled_button');
+ await component.waitForDisplayed({timeout: 5000});
+
+ // Get initial state (should be enabled)
+ const initialDump = await dumpVisualTree('dynamic_disabled_button');
+ expect(initialDump).toMatchSnapshot('initial-enabled');
+
+ // Click to disable
+ await component.click();
+
+ // Verify button is now disabled
+ const disabledDump = await dumpVisualTree('dynamic_disabled_button');
+ expect(disabledDump).toMatchSnapshot('disabled-state');
+ expect(disabledDump.Text).toContain('Disabled');
+
+ // Wait for auto re-enable (2 seconds)
+ await app.waitUntil(
+ async () => {
+ const dump = await dumpVisualTree('dynamic_disabled_button');
+ return dump.Text.includes('Disable Me');
+ },
+ {
+ timeout: 3000,
+ interval: 500,
+ timeoutMsg: 'Button should auto re-enable after 2 seconds',
+ }
+ );
+
+ // Verify button is enabled again
+ const reEnabledDump = await dumpVisualTree('dynamic_disabled_button');
+ expect(reEnabledDump).toMatchSnapshot('re-enabled-state');
+ });
+
+ test('Button should update relevant styling upon press', async () => {
+ await searchBox('dynamic styling');
+ const component = await app.findElementByTestID('dynamic_style_button');
+ await component.waitForDisplayed({timeout: 5000});
+
+ // Get initial state
+ const initialDump = await dumpVisualTree('dynamic_style_button');
+ expect(initialDump).toMatchSnapshot('initial-styling');
+
+ // Click to change styling
+ await component.click();
+
+ // Verify styling updated (should show press count and temporary color change)
+ const updatedDump = await dumpVisualTree('dynamic_style_button');
+ expect(updatedDump).toMatchSnapshot('updated-styling');
+ expect(updatedDump.Text).toContain('Style Button (1)');
+ });
});
From d80301ecdff3b8133c971756d4d45d22282169d0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Jun 2025 09:22:30 +0000
Subject: [PATCH 3/5] Fix missing testIDs for existing button containers and
enhance dynamic style test
Co-authored-by: anupriya13 <54227869+anupriya13@users.noreply.github.com>
---
.../tester/js/examples/Button/ButtonExample.js | 6 +++---
.../e2e-test-app-fabric/test/ButtonComponentTest.test.ts | 8 +++++++-
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/packages/@react-native/tester/js/examples/Button/ButtonExample.js b/packages/@react-native/tester/js/examples/Button/ButtonExample.js
index 60f388eb208..2167d8055c2 100644
--- a/packages/@react-native/tester/js/examples/Button/ButtonExample.js
+++ b/packages/@react-native/tester/js/examples/Button/ButtonExample.js
@@ -72,7 +72,7 @@ exports.examples = [
{theme => {
return (
-
+