Skip to content

Commit e40a816

Browse files
add method to check element clickable state (#3)
1 parent c4b2280 commit e40a816

12 files changed

+207
-51
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ migrate_working_dir/
1515
*.ipr
1616
*.iws
1717
.idea/
18+
.vscode
1819

1920
# The .vscode folder contains launch configuration and tasks you configure in
2021
# VS Code which you may wish to be included in version control, so this line

demo-app/android/gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
org.gradle.jvmargs=-Xmx1536M
1+
org.gradle.jvmargs=-Xmx4G
22
android.useAndroidX=true
33
android.enableJetifier=true

demo-app/lib/screens/double_and_long_tap_screen.dart

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class _DoubleTapScreenState extends State<DoubleTapScreen> {
2626
padding: const EdgeInsets.all(18.0),
2727
child: Semantics(
2828
label: "double_tap_button",
29+
key: const ValueKey("double_tap_button"),
2930
explicitChildNodes: true,
3031
container: true,
3132
child: InkWell(

demo-app/lib/screens/home_screen.dart

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:appium_testing_app/components/custom_app_bar.dart';
22
import 'package:appium_testing_app/models/feature_model.dart';
33
import 'package:appium_testing_app/screens/native_screen.dart';
44
import 'package:appium_testing_app/screens/slider_screen.dart';
5+
import 'package:appium_testing_app/screens/ui_elements_screen.dart';
56
import 'package:appium_testing_app/screens/vertical_swiping_screen.dart';
67
import 'package:appium_testing_app/screens/web_view_screen.dart';
78
import 'package:appium_testing_app/screens/wheel_picker_screen.dart';
@@ -46,6 +47,9 @@ class _HomeScreenState extends State<HomeScreen> {
4647
featureModels.add(FeatureModel(
4748
title: "Wheel Picker", subtitle: "Demos wheel picker color"));
4849
featureModels.add(FeatureModel(title: "Form", subtitle: "Demos for forms"));
50+
featureModels.add(FeatureModel(
51+
title: "UI Elements",
52+
subtitle: "Demos different ui elements with different states"));
4953
}
5054

5155
@override
@@ -115,6 +119,11 @@ class _HomeScreenState extends State<HomeScreen> {
115119
title: featureModels[index].title,
116120
);
117121
break;
122+
case 10:
123+
page = UiElementsScreen(
124+
title: featureModels[index].title,
125+
);
126+
break;
118127

119128
default:
120129
page = NativeScreen(title: featureModels[index].title);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import 'package:appium_testing_app/components/custom_app_bar.dart';
2+
import 'package:flutter/material.dart';
3+
4+
class UiElementsScreen extends StatefulWidget {
5+
final String title;
6+
7+
const UiElementsScreen({required this.title, super.key});
8+
9+
@override
10+
State<UiElementsScreen> createState() => _UiElementsScreenState();
11+
}
12+
13+
class _UiElementsScreenState extends State<UiElementsScreen> {
14+
@override
15+
Widget build(BuildContext context) {
16+
return Scaffold(
17+
appBar: CustomAppBarWidget(title: widget.title),
18+
body: Padding(
19+
padding: const EdgeInsets.all(16.0),
20+
child: ListView(
21+
children: [
22+
const SizedBox(
23+
height: 30,
24+
),
25+
Semantics(
26+
label: "enabled_text_field",
27+
// textField: true,
28+
explicitChildNodes: true,
29+
container: true,
30+
child: const TextField(
31+
decoration: InputDecoration(
32+
hintText: "Input",
33+
enabledBorder: UnderlineInputBorder(
34+
borderSide: BorderSide(color: Colors.grey)),
35+
),
36+
),
37+
),
38+
const SizedBox(
39+
height: 30,
40+
),
41+
Semantics(
42+
label: "disabled_text_field",
43+
// textField: true,
44+
explicitChildNodes: true,
45+
container: true,
46+
child: const TextField(
47+
enabled: false,
48+
decoration: InputDecoration(
49+
hintText: "Last Name",
50+
enabledBorder: UnderlineInputBorder(
51+
borderSide: BorderSide(color: Colors.grey)),
52+
),
53+
),
54+
),
55+
const SizedBox(
56+
height: 30,
57+
),
58+
Semantics(
59+
label: "enabled_checkbox",
60+
// textField: true,
61+
explicitChildNodes: true,
62+
container: true,
63+
child: const CheckboxListTile(
64+
title: Text(
65+
'Remember Password',
66+
style: TextStyle(color: Colors.grey),
67+
),
68+
value: true,
69+
onChanged: null,
70+
),
71+
),
72+
const SizedBox(
73+
height: 30,
74+
),
75+
Semantics(
76+
label: "disabled_checkbox",
77+
// textField: true,
78+
explicitChildNodes: true,
79+
container: true,
80+
child: CheckboxListTile(
81+
title: const Text(
82+
'Remember Password',
83+
style: TextStyle(color: Colors.grey),
84+
),
85+
value: true,
86+
onChanged: (bool? value) {},
87+
),
88+
),
89+
],
90+
),
91+
),
92+
);
93+
}
94+
}

demo-app/lib/screens/vertical_swiping_screen.dart

+6-4
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,20 @@ class VerticalSwipingScreen extends StatelessWidget {
3232
children: List.generate(
3333
_languages.length,
3434
(index) => Padding(
35-
padding: const EdgeInsets.only(bottom: 10, left: 20, right: 20),
36-
child: Container(
35+
padding: const EdgeInsets.only(
36+
bottom: 10, left: 20, right: 20),
37+
child: Container(
3738
height: 80,
38-
decoration: BoxDecoration(color: Colors.blue.shade800),
39+
decoration:
40+
BoxDecoration(color: Colors.blue.shade800),
3941
child: Center(
4042
child: Text(
4143
_languages[index],
4244
style: const TextStyle(fontSize: 24),
4345
),
4446
),
4547
),
46-
))),
48+
))),
4749
),
4850
),
4951
);

demo-app/pubspec.yaml

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
name: appium_testing_app
22
description: A new Flutter project.
33

4-
publish_to: 'none'
4+
publish_to: "none"
55

66
scripts:
7-
android: "cd android && ./gradlew app:assembleDebug -Ptarget=`pwd`/../integration_test/appium.dart && adb uninstall com.example.appium_testing_app && adb install -r `pwd`/../build/app/outputs/apk/debug/app-debug.apk"
7+
android: "cd android && ./gradlew app:assembleDebug -Ptarget=`pwd`/../integration_test/appium.dart && (adb uninstall com.example.appium_testing_app | exit 0) && adb install -r `pwd`/../build/app/outputs/apk/debug/app-debug.apk"
88
simulator: "flutter build ios integration_test/appium.dart --simulator && xcrun simctl install booted ./build/ios/iphonesimulator/Runner.app && xcrun simctl spawn booted log stream | grep flutter"
99

1010
version: 1.0.0+1
1111

1212
environment:
13-
sdk: '>=3.1.1 <4.0.0'
13+
sdk: ">=3.1.1 <4.0.0"
1414

1515
# Dependencies specify other packages that your package needs in order to work.
1616
# To automatically upgrade your package dependencies to the latest versions
@@ -24,7 +24,6 @@ dependencies:
2424
flutter:
2525
sdk: flutter
2626

27-
2827
# The following adds the Cupertino Icons font to your application.
2928
# Use with the CupertinoIcons class for iOS style icons.
3029
cupertino_icons: ^1.0.2
@@ -47,7 +46,6 @@ dev_dependencies:
4746

4847
# The following section is specific to Flutter packages.
4948
flutter:
50-
5149
# The following line ensures that the Material Icons font is
5250
# included with your application, so that you can use the icons in
5351
# the material Icons class.

server/lib/src/driver.dart

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import 'package:appium_flutter_server/src/exceptions/no_driver_exception.dart';
22
import 'package:appium_flutter_server/src/models/session.dart';
33
import 'package:flutter/widgets.dart';
44
import 'package:flutter_test/flutter_test.dart';
5+
import 'package:integration_test/integration_test.dart';
56
import 'package:uuid/uuid.dart';
67

78
class FlutterDriver {
89
late WidgetTester _tester;
910
late Widget _app;
11+
late IntegrationTestWidgetsFlutterBinding _binding;
1012
Session? _session;
1113

1214
FlutterDriver._();
@@ -16,10 +18,15 @@ class FlutterDriver {
1618

1719
Widget get app => _app;
1820
WidgetTester get tester => _tester;
21+
IntegrationTestWidgetsFlutterBinding get binding => _binding;
1922

20-
void initialize({required WidgetTester tester, required Widget app}) async {
23+
void initialize(
24+
{required WidgetTester tester,
25+
required Widget app,
26+
required IntegrationTestWidgetsFlutterBinding binding}) async {
2127
_tester = tester;
2228
_app = app;
29+
_binding = binding;
2330
}
2431

2532
String initializeSession(Map<String, dynamic> capabilities) {

server/lib/src/handler/get_attribute.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class GetAttributeHandler extends RequestHandler {
3131
log("${node.name} -> ${node.value}");
3232
}
3333

34-
String? result = await ElementHelper.getAttribute(element, attribute);
34+
dynamic result = await ElementHelper.getAttribute(element, attribute);
3535

3636
return AppiumResponse(getSessionId(request), result);
3737
} catch (e) {

server/lib/src/internal/element_lookup_strategy.dart

+9-7
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,21 @@ extension ElementLookupStrategyExtension on ElementLookupStrategy {
3131
Finder toFinder(dynamic selector) {
3232
switch (this) {
3333
case ElementLookupStrategy.BY_KEY:
34-
return find.byKey(Key(selector));
34+
return find.byKey(Key(selector), skipOffstage: false);
3535
case ElementLookupStrategy.BY_SEMANTICS_LABEL:
36-
return find.bySemanticsLabel(selector);
36+
return find.bySemanticsLabel(selector, skipOffstage: false);
3737
case ElementLookupStrategy.BY_TOOLTIP:
38-
return find.byTooltip(selector);
38+
return find.byTooltip(selector, skipOffstage: false);
3939
case ElementLookupStrategy.BY_TEXT:
40-
return find.text(selector);
40+
return find.text(selector, skipOffstage: false);
4141
case ElementLookupStrategy.BY_TEXT_CONTAINING:
42-
return find.textContaining(selector);
42+
return find.textContaining(selector, skipOffstage: false);
4343
case ElementLookupStrategy.BY_WIDGET_NAME:
44-
return find.byWidgetPredicate(filterByWidgetName(selector));
44+
return find.byWidgetPredicate(filterByWidgetName(selector),
45+
skipOffstage: false);
4546
case ElementLookupStrategy.BY_ICON_POINT:
46-
return find.byWidgetPredicate(filterByIconCode(int.parse(selector)));
47+
return find.byWidgetPredicate(filterByIconCode(int.parse(selector)),
48+
skipOffstage: false);
4749
// return find.byIcon(const IconData(0xe0c4));
4850
// case ElementLookupStrategy.BY_ELEMENT_PREDICATE:
4951
// return find.byElementPredicate(Key(selector));

server/lib/src/runner.dart

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@ import 'package:appium_flutter_server/src/appium_test_bindings.dart';
55
import 'package:flutter/widgets.dart';
66
import 'package:flutter_test/flutter_test.dart';
77
import 'package:appium_flutter_server/src/server.dart';
8+
import 'package:integration_test/integration_test.dart';
89

910
const MAX_TEST_DURATION_SECS = 24 * 60 * 60;
1011

1112
void initializeTest({required Widget app}) async {
12-
AppiumTestWidgetsFlutterBinding.ensureInitialized();
13+
IntegrationTestWidgetsFlutterBinding binding =
14+
AppiumTestWidgetsFlutterBinding.ensureInitialized();
1315

1416
testWidgets('appium flutter server', (tester) async {
1517
/* Initialize network tools */
1618
// final appDocDirectory = await getApplicationDocumentsDirectory();
1719
// await configureNetworkTools(appDocDirectory.path, enableDebugging: true);
18-
FlutterDriver.instance.initialize(tester: tester, app: app);
20+
FlutterDriver.instance
21+
.initialize(tester: tester, app: app, binding: binding);
1922
await tester.pumpWidget(app);
2023
// await tester.tap(find.text("Form widgets"));
2124
// await tester.pumpAndSettle();

0 commit comments

Comments
 (0)