Skip to content

Commit 8149e22

Browse files
rubennortemeta-codesync[bot]
authored andcommitted
Add Fantom tests for ActivityIndicator and Switch (#57548)
Summary: Pull Request resolved: #57548 Adds Fantom `-itest.js` coverage for two public components that were previously untested: `ActivityIndicator` (small/large/numeric sizes and prop forwarding) and `Switch` (on/off/disabled rendering, track/thumb color resolution, and `onValueChange`/`onChange` firing when the native switch toggles). Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D111908071 fbshipit-source-id: 795e6f88a52d64221990e1e61c35541b7c48571d
1 parent 704e286 commit 8149e22

2 files changed

Lines changed: 100 additions & 193 deletions

File tree

packages/react-native/Libraries/Components/ActivityIndicator/__tests__/ActivityIndicator-itest.js

Lines changed: 35 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -6,189 +6,53 @@
66
*
77
* @flow strict-local
88
* @format
9+
* @oncall react_native
910
*/
1011

1112
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1213

13-
import type {HostInstance} from 'react-native';
14-
1514
import * as Fantom from '@react-native/fantom';
16-
import nullthrows from 'nullthrows';
1715
import * as React from 'react';
18-
import {createRef} from 'react';
1916
import {ActivityIndicator} from 'react-native';
2017

21-
describe('<ActivityIndicator>', () => {
22-
it('sets displayName', () => {
23-
expect(ActivityIndicator.displayName).toBe('ActivityIndicator');
18+
function renderSizeOutput(element: React.MixedElement): React.Node {
19+
const root = Fantom.createRoot();
20+
Fantom.runTask(() => {
21+
root.render(element);
2422
});
25-
26-
describe('props', () => {
27-
describe('size', () => {
28-
it('defaults to "small" (20x20)', () => {
29-
const root = Fantom.createRoot();
30-
31-
Fantom.runTask(() => {
32-
root.render(<ActivityIndicator />);
33-
});
34-
35-
expect(root.getRenderedOutput().toJSX()).toEqual(
36-
<rn-androidProgressBar height="20" width="20" />,
37-
);
38-
});
39-
40-
it('renders with size "small"', () => {
41-
const root = Fantom.createRoot();
42-
43-
Fantom.runTask(() => {
44-
root.render(<ActivityIndicator size="small" />);
45-
});
46-
47-
expect(root.getRenderedOutput().toJSX()).toEqual(
48-
<rn-androidProgressBar height="20" width="20" />,
49-
);
50-
});
51-
52-
it('renders with size "large" (36x36)', () => {
53-
const root = Fantom.createRoot();
54-
55-
Fantom.runTask(() => {
56-
root.render(<ActivityIndicator size="large" />);
57-
});
58-
59-
expect(root.getRenderedOutput().toJSX()).toEqual(
60-
<rn-androidProgressBar height="36" width="36" />,
61-
);
62-
});
63-
64-
it('renders with numeric size on Android', () => {
65-
const root = Fantom.createRoot();
66-
67-
Fantom.runTask(() => {
68-
root.render(<ActivityIndicator size={48} />);
69-
});
70-
71-
expect(root.getRenderedOutput().toJSX()).toEqual(
72-
<rn-androidProgressBar height="48" width="48" />,
73-
);
74-
});
75-
});
76-
77-
describe('color', () => {
78-
it('renders an AndroidProgressBar when color is set', () => {
79-
const root = Fantom.createRoot();
80-
81-
Fantom.runTask(() => {
82-
root.render(<ActivityIndicator color="red" />);
83-
});
84-
85-
// Color is a native prop not serialized as a view attribute,
86-
// but the component still renders correctly
87-
expect(root.getRenderedOutput().toJSX()).toEqual(
88-
<rn-androidProgressBar height="20" width="20" />,
89-
);
90-
});
91-
});
92-
93-
describe('animating', () => {
94-
it('defaults to true', () => {
95-
const root = Fantom.createRoot();
96-
97-
Fantom.runTask(() => {
98-
root.render(<ActivityIndicator />);
99-
});
100-
101-
// Component renders normally when animating (default)
102-
expect(root.getRenderedOutput().toJSX()).toEqual(
103-
<rn-androidProgressBar height="20" width="20" />,
104-
);
105-
});
106-
107-
it('renders when animating is false', () => {
108-
const root = Fantom.createRoot();
109-
110-
Fantom.runTask(() => {
111-
root.render(<ActivityIndicator animating={false} />);
112-
});
113-
114-
// Component still renders when not animating
115-
expect(root.getRenderedOutput().toJSX()).toEqual(
116-
<rn-androidProgressBar height="20" width="20" />,
117-
);
118-
});
119-
});
120-
121-
describe('style', () => {
122-
it('applies wrapper View style', () => {
123-
const root = Fantom.createRoot();
124-
125-
Fantom.runTask(() => {
126-
root.render(<ActivityIndicator style={{opacity: 0.5}} />);
127-
});
128-
129-
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
130-
<rn-view opacity="0.5">
131-
<rn-androidProgressBar />
132-
</rn-view>,
133-
);
134-
});
135-
});
136-
137-
describe('accessibilityLabel', () => {
138-
it('is propagated to the native component', () => {
139-
const root = Fantom.createRoot();
140-
141-
Fantom.runTask(() => {
142-
root.render(
143-
<ActivityIndicator accessibilityLabel="Loading content" />,
144-
);
145-
});
146-
147-
expect(
148-
root.getRenderedOutput({props: ['accessibilityLabel']}).toJSX(),
149-
).toEqual(
150-
<rn-androidProgressBar accessibilityLabel="Loading content" />,
151-
);
152-
});
153-
});
154-
155-
describe('testID', () => {
156-
it('is propagated to the native component', () => {
157-
const root = Fantom.createRoot();
158-
159-
Fantom.runTask(() => {
160-
root.render(<ActivityIndicator testID="loading-spinner" />);
161-
});
162-
163-
expect(root.getRenderedOutput({props: ['testID']}).toJSX()).toEqual(
164-
<rn-androidProgressBar testID="loading-spinner" />,
165-
);
166-
});
167-
});
23+
return root.getRenderedOutput({props: ['width', 'height']}).toJSX();
24+
}
25+
26+
describe('ActivityIndicator', () => {
27+
it('renders the default (small) size', () => {
28+
expect(renderSizeOutput(<ActivityIndicator />)).toEqual(
29+
<rn-androidProgressBar width="20" height="20" />,
30+
);
16831
});
16932

170-
describe('ref', () => {
171-
it('provides a valid HTMLElement instance', () => {
172-
const elementRef = createRef<HostInstance>();
173-
const root = Fantom.createRoot();
174-
175-
Fantom.runTask(() => {
176-
root.render(<ActivityIndicator ref={elementRef} />);
177-
});
178-
179-
expect(elementRef.current).toBeInstanceOf(HTMLElement);
180-
});
181-
182-
it('has the correct tag name', () => {
183-
const elementRef = createRef<HostInstance>();
184-
const root = Fantom.createRoot();
33+
it('renders the large size', () => {
34+
expect(renderSizeOutput(<ActivityIndicator size="large" />)).toEqual(
35+
<rn-androidProgressBar width="36" height="36" />,
36+
);
37+
});
18538

186-
Fantom.runTask(() => {
187-
root.render(<ActivityIndicator ref={elementRef} />);
188-
});
39+
it('renders a numeric size as an explicit width/height', () => {
40+
expect(renderSizeOutput(<ActivityIndicator size={42} />)).toEqual(
41+
<rn-androidProgressBar width="42" height="42" />,
42+
);
43+
});
18944

190-
const element = nullthrows(elementRef.current);
191-
expect(element.tagName).toBe('RN:AndroidProgressBar');
192-
});
45+
it('renders with color, animating and hidesWhenStopped props applied', () => {
46+
// color/animating/hidesWhenStopped are forwarded to the native component;
47+
// the mounted size still reflects the (default, small) size.
48+
expect(
49+
renderSizeOutput(
50+
<ActivityIndicator
51+
color="#ff0000"
52+
animating={false}
53+
hidesWhenStopped={false}
54+
/>,
55+
),
56+
).toEqual(<rn-androidProgressBar width="20" height="20" />);
19357
});
19458
});

packages/react-native/Libraries/Components/Switch/__tests__/Switch-itest.js

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
* @flow strict-local
88
* @format
9+
* @oncall react_native
910
*/
1011

1112
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
@@ -18,30 +19,72 @@ import * as React from 'react';
1819
import {createRef} from 'react';
1920
import {Switch} from 'react-native';
2021

21-
describe('<ExampleComponent>', () => {
22-
describe('props', () => {
23-
describe('exampleProp', () => {
24-
// more describe('<context>') or tests with it('<behaviour>')
25-
});
26-
// ... more props
22+
function render(element: React.MixedElement): Fantom.Root {
23+
const root = Fantom.createRoot();
24+
Fantom.runTask(() => {
25+
root.render(element);
26+
});
27+
return root;
28+
}
29+
30+
describe('Switch', () => {
31+
it('renders the native switch', () => {
32+
const root = render(<Switch value={true} />);
33+
34+
expect(
35+
root.getRenderedOutput({props: ['accessibilityRole']}).toJSX(),
36+
).toEqual(<rn-androidSwitch accessibilityRole="switch" />);
37+
});
38+
39+
it('reflects the disabled state via accessibilityState', () => {
40+
const root = render(<Switch value={false} disabled={true} />);
41+
42+
expect(
43+
root.getRenderedOutput({props: ['accessibilityState']}).toJSX(),
44+
).toEqual(
45+
<rn-androidSwitch accessibilityState="{disabled:true,selected:false,checked:None,busy:false,expanded:null}" />,
46+
);
2747
});
28-
describe('ref', () => {
29-
describe('exampleMethod()', () => {
30-
// more describe('<context>') or tests with it('<behaviour>')
48+
49+
it('renders with track and thumb color props applied', () => {
50+
// Exercises the color-resolution path; the mounted switch still renders as
51+
// the native switch host.
52+
const root = render(
53+
<Switch
54+
value={true}
55+
thumbColor="#ff0000"
56+
trackColor={{true: '#00ff00', false: '#0000ff'}}
57+
ios_backgroundColor="#cccccc"
58+
/>,
59+
);
60+
61+
expect(
62+
root.getRenderedOutput({props: ['accessibilityRole']}).toJSX(),
63+
).toEqual(<rn-androidSwitch accessibilityRole="switch" />);
64+
});
65+
66+
it('fires onValueChange and onChange when the native switch toggles', () => {
67+
const onValueChange = jest.fn();
68+
const onChange = jest.fn();
69+
const ref = createRef<HostInstance>();
70+
const root = Fantom.createRoot();
71+
72+
Fantom.runTask(() => {
73+
root.render(
74+
<Switch
75+
ref={ref}
76+
value={false}
77+
onValueChange={onValueChange}
78+
onChange={onChange}
79+
/>,
80+
);
3181
});
32-
// ... more methods
33-
describe('instance', () => {
34-
it('uses the "RN:Switch" tag name', () => {
35-
const elementRef = createRef<HostInstance>();
36-
const root = Fantom.createRoot();
37-
Fantom.runTask(() => {
38-
root.render(<Switch ref={elementRef} />);
39-
});
40-
41-
expect(elementRef.current).toBeInstanceOf(HTMLElement);
42-
const element = nullthrows(elementRef.current);
43-
expect(element.tagName).toBe('RN:Switch');
44-
});
82+
83+
Fantom.dispatchNativeEvent(nullthrows(ref.current), 'change', {
84+
value: true,
4585
});
86+
87+
expect(onValueChange).toHaveBeenCalledWith(true);
88+
expect(onChange).toHaveBeenCalled();
4689
});
4790
});

0 commit comments

Comments
 (0)