Skip to content

Commit a310997

Browse files
SConawayvonovak
authored andcommitted
Add appearance iOS-only prop to JS
and something for iOS wip wip wip
1 parent d8ae932 commit a310997

18 files changed

+463
-227
lines changed

example/App.js

+55-79
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,18 @@ import {
1111
useColorScheme,
1212
} from 'react-native';
1313
import DateTimePicker from '@react-native-community/datetimepicker';
14+
import SegmentedControl from '@react-native-community/segmented-control';
1415
import {Colors} from 'react-native/Libraries/NewAppScreen';
1516
import React, {useState} from 'react';
1617
import {Picker} from 'react-native-windows';
1718
import moment from 'moment';
18-
import {DAY_OF_WEEK} from '../src/constants';
19+
import {
20+
ANDROID_MODE,
21+
DAY_OF_WEEK,
22+
IOS_MODE,
23+
ANDROID_DISPLAY,
24+
IOS_DISPLAY,
25+
} from '../src/constants';
1926

2027
const ThemedText = props => {
2128
const isDarkMode = useColorScheme() === 'dark';
@@ -28,13 +35,23 @@ const ThemedText = props => {
2835
});
2936
};
3037

38+
const MODE_VALUES = Platform.select({
39+
ios: Object.values(IOS_MODE),
40+
android: Object.values(ANDROID_MODE),
41+
});
42+
const DISPLAY_VALUES = Platform.select({
43+
ios: Object.values(IOS_DISPLAY),
44+
android: Object.values(ANDROID_DISPLAY),
45+
});
46+
const MINUTE_INTERVALS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30];
47+
3148
export const App = () => {
3249
const [date, setDate] = useState(new Date(1598051730000));
33-
const [mode, setMode] = useState('date');
50+
const [mode, setMode] = useState(MODE_VALUES[0]);
3451
const [show, setShow] = useState(false);
3552
const [color, setColor] = useState();
36-
const [display, setDisplay] = useState('default');
37-
const [interval, setMinInterval] = useState(undefined);
53+
const [display, setDisplay] = useState(DISPLAY_VALUES[0]);
54+
const [interval, setMinInterval] = useState(1);
3855

3956
// Windows-specific
4057
const [maxDate, setMinDate] = useState(new Date('2021'));
@@ -56,43 +73,6 @@ export const App = () => {
5673
setDate(currentDate);
5774
};
5875

59-
const showMode = currentMode => {
60-
setShow(true);
61-
setMode(currentMode);
62-
};
63-
64-
const showDatepicker = () => {
65-
showMode('date');
66-
setDisplay('default');
67-
};
68-
69-
const showDatepickerSpinner = () => {
70-
showMode('date');
71-
setDisplay('spinner');
72-
};
73-
74-
const showTimepicker = () => {
75-
showMode('time');
76-
setDisplay('default');
77-
};
78-
79-
const showTimepickerSpinner = () => {
80-
showMode('time');
81-
setDisplay('spinner');
82-
};
83-
84-
const showTimepickerClockModeWithInterval = () => {
85-
showMode('time');
86-
setMinInterval(5);
87-
setDisplay('clock');
88-
};
89-
90-
const showTimepickerSpinnerWithInterval = () => {
91-
showMode('time');
92-
setMinInterval(5);
93-
setDisplay('spinner');
94-
};
95-
9676
const isDarkMode = useColorScheme() === 'dark';
9777

9878
const backgroundStyle = {
@@ -121,6 +101,34 @@ export const App = () => {
121101
Example DateTime Picker
122102
</ThemedText>
123103
</View>
104+
<ThemedText>mode prop:</ThemedText>
105+
<SegmentedControl
106+
values={MODE_VALUES}
107+
selectedIndex={MODE_VALUES.indexOf(mode)}
108+
onChange={event => {
109+
setMode(MODE_VALUES[event.nativeEvent.selectedSegmentIndex]);
110+
}}
111+
/>
112+
<ThemedText>display prop:</ThemedText>
113+
<SegmentedControl
114+
values={DISPLAY_VALUES}
115+
selectedIndex={DISPLAY_VALUES.indexOf(display)}
116+
onChange={event => {
117+
setDisplay(
118+
DISPLAY_VALUES[event.nativeEvent.selectedSegmentIndex],
119+
);
120+
}}
121+
/>
122+
<ThemedText>minute interval prop:</ThemedText>
123+
<SegmentedControl
124+
values={MINUTE_INTERVALS.map(String)}
125+
selectedIndex={MINUTE_INTERVALS.indexOf(interval)}
126+
onChange={event => {
127+
setMinInterval(
128+
MINUTE_INTERVALS[event.nativeEvent.selectedSegmentIndex],
129+
);
130+
}}
131+
/>
124132
<View style={styles.header}>
125133
<ThemedText style={{margin: 10, flex: 1}}>
126134
text color (iOS only)
@@ -136,46 +144,14 @@ export const App = () => {
136144
</View>
137145
<View style={styles.button}>
138146
<Button
139-
testID="datePickerButton"
140-
onPress={showDatepicker}
141-
title="Show date picker default!"
142-
/>
143-
</View>
144-
<View style={styles.button}>
145-
<Button
146-
testID="datePickerButtonSpinner"
147-
onPress={showDatepickerSpinner}
148-
title="Show date picker spinner!"
149-
/>
150-
</View>
151-
<View style={styles.button}>
152-
<Button
153-
testID="timePickerButton"
154-
onPress={showTimepicker}
155-
title="Show time picker!"
156-
/>
157-
</View>
158-
<View style={styles.button}>
159-
<Button
160-
testID="timePickerButtonSpinner"
161-
onPress={showTimepickerSpinner}
162-
title="Show time picker spinner!"
163-
/>
164-
</View>
165-
<View style={styles.button}>
166-
<Button
167-
testID="timePickerDefaultIntervalButton"
168-
onPress={showTimepickerClockModeWithInterval}
169-
title="Show time picker as clock (with 5 min interval)!"
170-
/>
171-
</View>
172-
<View style={styles.button}>
173-
<Button
174-
testID="timePickerSpinnerIntervalButton"
175-
onPress={showTimepickerSpinnerWithInterval}
176-
title="Show time picker as spinner (with 5 min interval)!"
147+
testID="showPickerButton"
148+
onPress={() => {
149+
setShow(true);
150+
}}
151+
title="Show picker!"
177152
/>
178153
</View>
154+
179155
<View style={styles.header}>
180156
<ThemedText testID="dateText" style={styles.dateTimeText}>
181157
{moment.utc(date).format('MM/DD/YYYY')}
Binary file not shown.

example/e2e/detoxTest.spec.js

+45-15
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,36 @@ async function userChangesMinuteValue() {
1414
await minuteTextinput.replaceText('30');
1515
}
1616

17+
async function userOpensPicker({mode, display, interval}) {
18+
await element(by.text(mode)).tap();
19+
await element(by.text(display)).tap();
20+
if (interval) {
21+
await element(by.text(String(interval))).tap();
22+
}
23+
await element(by.id('showPickerButton')).tap();
24+
}
25+
26+
async function userTapsCancelButtonAndroid() {
27+
// selecting element by text does not work consistently :/
28+
// const cancelButton = element(by.text('Cancel'));
29+
const cancelButton = element(
30+
by
31+
.type('androidx.appcompat.widget.AppCompatButton')
32+
.withAncestor(by.type('android.widget.ScrollView')),
33+
).atIndex(0);
34+
await cancelButton.tap();
35+
}
36+
async function userTapsOkButtonAndroid() {
37+
// selecting element by text does not work consistently :/
38+
// const okButton = element(by.text('OK'));
39+
const okButton = element(
40+
by
41+
.type('androidx.appcompat.widget.AppCompatButton')
42+
.withAncestor(by.type('android.widget.ScrollView')),
43+
).atIndex(1);
44+
await okButton.tap();
45+
}
46+
1747
describe('Example', () => {
1848
beforeEach(async () => {
1949
if (global.device.getPlatform() === 'ios') {
@@ -34,7 +64,7 @@ describe('Example', () => {
3464
});
3565

3666
it('should show date picker after tapping datePicker button', async () => {
37-
await element(by.id('datePickerButton')).tap();
67+
await userOpensPicker({mode: 'date', display: 'default'});
3868

3969
if (global.device.getPlatform() === 'ios') {
4070
await expect(
@@ -46,7 +76,7 @@ describe('Example', () => {
4676
});
4777

4878
it('Nothing should happen if date does not change', async () => {
49-
await element(by.id('datePickerButton')).tap();
79+
await userOpensPicker({mode: 'date', display: 'default'});
5080

5181
if (global.device.getPlatform() === 'ios') {
5282
await expect(
@@ -60,15 +90,15 @@ describe('Example', () => {
6090
);
6191
await testElement.swipe('left', 'fast', '100');
6292
await testElement.tapAtPoint({x: 50, y: 200});
63-
await element(by.text('CANCEL')).tap();
93+
await userTapsCancelButtonAndroid();
6494
}
6595

6696
const dateText = getDateText();
6797
await expect(dateText).toHaveText('08/21/2020');
6898
});
6999

70100
it('should update dateTimeText when date changes', async () => {
71-
await element(by.id('datePickerButton')).tap();
101+
await userOpensPicker({mode: 'date', display: 'default'});
72102
const dateText = getDateText();
73103

74104
if (global.device.getPlatform() === 'ios') {
@@ -88,14 +118,14 @@ describe('Example', () => {
88118
);
89119
await testElement.swipe('left', 'fast', '100');
90120
await testElement.tapAtPoint({x: 50, y: 200});
91-
await element(by.text('OK')).tap();
121+
await userTapsOkButtonAndroid();
92122

93123
await expect(dateText).toHaveText('09/13/2020');
94124
}
95125
});
96126

97127
it('should show time picker after tapping timePicker button', async () => {
98-
await element(by.id('timePickerButton')).tap();
128+
await userOpensPicker({mode: 'time', display: 'default'});
99129

100130
if (global.device.getPlatform() === 'ios') {
101131
await expect(
@@ -107,22 +137,22 @@ describe('Example', () => {
107137
});
108138

109139
it('Nothing should happen if time does not change', async () => {
110-
await element(by.id('timePickerButton')).tap();
140+
await userOpensPicker({mode: 'time', display: 'default'});
111141

112142
if (global.device.getPlatform() === 'ios') {
113143
await expect(
114144
element(by.type('UIPickerView').withAncestor(by.id('dateTimePicker'))),
115145
).toBeVisible();
116146
} else {
117147
await userChangesMinuteValue();
118-
await element(by.text('CANCEL')).tap();
148+
await userTapsCancelButtonAndroid();
119149
}
120150
const timeText = getTimeText();
121151
await expect(timeText).toHaveText('23:15');
122152
});
123153

124154
it('should change time text when time changes', async () => {
125-
await element(by.id('timePickerButton')).tap();
155+
await userOpensPicker({mode: 'time', display: 'default'});
126156
const timeText = getTimeText();
127157

128158
if (global.device.getPlatform() === 'ios') {
@@ -136,7 +166,7 @@ describe('Example', () => {
136166
await expect(timeText).toHaveText('14:44');
137167
} else {
138168
await userChangesMinuteValue();
139-
await element(by.text('OK')).tap();
169+
await userTapsOkButtonAndroid();
140170

141171
await expect(timeText).toHaveText('23:30');
142172
}
@@ -145,7 +175,7 @@ describe('Example', () => {
145175
describe('given 5-minute interval', () => {
146176
it(':android: clock picker should correct 18-minute selection to 20-minute one', async () => {
147177
try {
148-
await element(by.id('timePickerDefaultIntervalButton')).tap();
178+
await userOpensPicker({mode: 'time', display: 'clock', interval: 5});
149179

150180
const keyboardButton = element(
151181
by.type('androidx.appcompat.widget.AppCompatImageButton'),
@@ -156,7 +186,7 @@ describe('Example', () => {
156186
).atIndex(1);
157187
await testElement.tap();
158188
await testElement.replaceText('18');
159-
await element(by.text('OK')).tap();
189+
await userTapsOkButtonAndroid();
160190

161191
const timeText = getTimeText();
162192
await expect(timeText).toHaveText('23:20');
@@ -171,13 +201,13 @@ describe('Example', () => {
171201

172202
await expect(timeText).toHaveText('23:15');
173203

174-
await element(by.id('timePickerSpinnerIntervalButton')).tap();
204+
await userOpensPicker({mode: 'time', display: 'spinner', interval: 5});
175205

176206
const minutePicker = element(
177207
by.type('android.widget.NumberPicker'),
178208
).atIndex(1);
179209
await minutePicker.swipe('up', 'slow', '33');
180-
await element(by.text('OK')).tap();
210+
await userTapsOkButtonAndroid();
181211

182212
await expect(timeText).toHaveText('23:25');
183213
} catch (err) {
@@ -186,7 +216,7 @@ describe('Example', () => {
186216
});
187217

188218
it(':ios: picker should offer only options divisible by 5 (0, 5, 10,...)', async () => {
189-
await element(by.id('timePickerDefaultIntervalButton')).tap();
219+
await userOpensPicker({mode: 'time', display: 'spinner', interval: 5});
190220

191221
const testElement = element(
192222
by.type('UIPickerView').withAncestor(by.id('dateTimePicker')),

0 commit comments

Comments
 (0)