Skip to content

Commit d7846d7

Browse files
authored
Merge pull request #4 from sncf-connect-tech/example_app
add example lib
2 parents 81c1cf2 + 0cd58eb commit d7846d7

File tree

93 files changed

+2178
-49
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+2178
-49
lines changed

README.md

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,31 @@ set up the configuration and you are ready to describe actions and assertions of
2424
## Table of Contents
2525

2626
<!-- TOC -->
27-
* [Table of Contents](#table-of-contents)
28-
* [-- Features](#---features)
29-
* [-- Getting started](#---getting-started)
27+
* [Table of Contents](#table-of-contents)
28+
* [-- Features](#---features)
29+
* [-- Getting started](#---getting-started)
3030
* [🥒 Add `gherkin_widget_extension` dependency](#-add-gherkin_widget_extension-dependency)
3131
* [✏️ Write a scenario](#%EF%B8%8F-write-a-scenario)
3232
* [🔗 Declare step definitions](#-declare-step-definitions)
3333
* [⚙️ Add some configuration](#%EF%B8%8F-add-some-configuration)
34-
* [Package distinctive features](#package-distinctive-features)
35-
* [`..hooks`](#hooks)
36-
* [`..reporters`](#reporters)
34+
* [Package distinctive features](#package-distinctive-features)
35+
* [`..hooks`](#hooks)
36+
* [`..reporters`](#reporters)
3737
* [🧪 Set up the test runner](#-set-up-the-test-runner)
3838
* [🪄 Run your tests](#-run-your-tests)
3939
* [🎬️ Let's go!](#%EF%B8%8F-lets-go)
40-
* [-- Usage](#---usage)
40+
* [-- Usage](#---usage)
4141
* [🌎 `WidgetCucumberWorld` advantages](#-widgetcucumberworld-advantages)
4242
* [🪣 Buckets for data](#-buckets-for-data)
4343
* [👁️ Don't forget the accessibility](#%EF%B8%8F-dont-forget-the-accessibility)
4444
* [🔄 Loading data for widgets with `JsonLoader`](#-loading-data-for-widgets-with-jsonloader)
4545
* [📸 A Hook for screenshot and widget tree rendering](#-a-hook-for-screenshot-and-widget-tree-rendering)
4646
* [📋 Widget test reporters](#-widget-test-reporters)
47-
* [`MonochromePrinter`](#monochromeprinter)
48-
* [`WidgetStdoutReporter`](#widgetstdoutreporter)
49-
* [`WidgetTestRunSummaryReporter`](#widgettestrunsummaryreporter)
50-
* [`XmlReporter`](#xmlreporter)
51-
* [Add reporters in test configuration](#add-reporters-in-test-configuration)
47+
* [`MonochromePrinter`](#monochromeprinter)
48+
* [`WidgetStdoutReporter`](#widgetstdoutreporter)
49+
* [`WidgetTestRunSummaryReporter`](#widgettestrunsummaryreporter)
50+
* [`XmlReporter`](#xmlreporter)
51+
* [Add reporters in test configuration](#add-reporters-in-test-configuration)
5252
<!-- TOC -->
5353

5454
***
@@ -102,8 +102,10 @@ Next step: implementation of step definitions.
102102

103103
### 🔗 Declare step definitions
104104

105-
Step definitions are like links between the gherkin sentence and the code that interacts with the widget. Usually `given`
106-
steps are used to set up the test context, `when` step(s) represents the main action of the test (When the user validates
105+
Step definitions are like links between the gherkin sentence and the code that interacts with the widget.
106+
Usually `given`
107+
steps are used to set up the test context, `when` step(s) represents the main action of the test (When the user
108+
validates
107109
the form, When the user applies his choice, ...) and the `then` steps assert everything assertable on the screen
108110
(text, state, semantics, ...).
109111

@@ -184,7 +186,7 @@ More information [here](#-widget-test-reporters).
184186

185187
### 🧪 Set up the test runner
186188

187-
Create a new file `widget_test_runner.dart` in `test` folder and call the test runner method:
189+
Create a new file `widget_test_runner.dart` in the `test` folder and call the test runner method:
188190

189191
```dart
190192
void main() {
@@ -193,6 +195,16 @@ void main() {
193195
}
194196
```
195197

198+
Create another file named `flutter_test_config.dart` in the `test` folder and declare the test executing configuration
199+
to enable font loading _(required for screenshots)_:
200+
201+
```dart
202+
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
203+
await loadAppFonts();
204+
await testMain();
205+
}
206+
```
207+
196208
### 🪄 Run your tests
197209

198210
Open a terminal and execute the file you created before:
@@ -274,32 +286,35 @@ Keep in mind that bucket type is required to use it and access to its data (here
274286
### 👁️ Don't forget the accessibility
275287

276288
Accessibility is essential in mobile application and must be tested as well. This package provides a method to test
277-
widget semantics:
289+
widget semantics:
278290

279291
```dart
280292
Finder widgetWithSemanticLabel(
281-
Type widgetType,
282-
String semanticLabel,
283-
{bool skipOffstage = true,
284-
Matcher? semanticMatcher}
293+
Type widgetType,
294+
String semanticLabel,
295+
{bool skipOffstage = true,
296+
Matcher? semanticMatcher}
285297
)
286298
```
287299

288300
This method allows you to find a widget by its type, its semantic label and its full semantics:
301+
289302
```dart
303+
290304
final widgetToFind = find.widgetWithSemanticLabel(Checkbox, "Checkbox label",
291-
semanticMatcher: matchesSemantics(
292-
hasEnabledState: true,
293-
label: "Checkbox label",
294-
hasTapAction: true,
295-
isEnabled: true,
296-
isFocusable: true,
297-
textDirection: TextDirection.ltr,
298-
hasCheckedState: true,
299-
isChecked: true));
300-
301-
expect(widgetToFind, findsOneWidget);
305+
semanticMatcher: matchesSemantics(
306+
hasEnabledState: true,
307+
label: "Checkbox label",
308+
hasTapAction: true,
309+
isEnabled: true,
310+
isFocusable: true,
311+
textDirection: TextDirection.ltr,
312+
hasCheckedState: true,
313+
isChecked: true));
314+
315+
expect(widgetToFind, findsOneWidget);
302316
```
317+
303318
The `expect` raises an `AssertionError` if no corresponding widget exists.
304319

305320
### 🔄 Loading data for widgets with `JsonLoader`
@@ -314,9 +329,14 @@ var jsonMap = await JsonLoader.loadJson("path/to/json/folder");
314329
```
315330
`jsonMap` contains a map where keys are json filenames and values the json files content.
316331

317-
318332
### 📸 A Hook for screenshot and widget tree rendering
319333

334+
> 📣 At least one font must be declared in the `pubspec.yml` to have nice and understandable screenshots (Squares will
335+
> replace fonts otherwise).
336+
>
337+
> 📣 The `flutter_test_config.dart` must exist at the root of `test` directory (
338+
> See [🧪 Set up the test runner](#-set-up-the-test-runner) paragraph).
339+
320340
Hooks contain methods executed before or after specific milestones during a test driven by Cucumber (before/after scenario,
321341
before/after steps, ...). More information about Hooks [here](https://pub.dev/packages/gherkin#hooks).
322342

@@ -328,7 +348,8 @@ TestConfiguration()
328348
..hooks = [WidgetHooks(dumpFolderPath: 'widget_tests_report_folder')]
329349
```
330350

331-
**Parameter `dumpFolderPath` is mandatory**: it represents the report folder where screenshots and widget rendering will be
351+
**Parameter `dumpFolderPath` is mandatory**: it represents the report folder where screenshots and widget rendering will
352+
be
332353
stored on test failure.
333354

334355
> 📣 This package provides a custom Widget called `MaterialTestWidget`. This widget must encapsulate the widget to pump
@@ -347,6 +368,7 @@ to print your message in the log console without any decorations/emojis/whatever
347368
#### `WidgetStdoutReporter`
348369

349370
This reporter is in charge of:
371+
350372
* printing the name of the running scenario with its file location,
351373
* printing each step with its status and time duration
352374
* `√` if step succeeded
@@ -396,14 +418,15 @@ On failure, a link to the screenshot is also provided.
396418
> Report [here](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html).
397419

398420
#### Add reporters in test configuration
421+
399422
To benefit from supplied reporters, they need to be added on the `TestConfiguration`:
400423
```dart
401424
TestConfiguration()
402-
..reporters = [
403-
WidgetStdoutReporter(),
404-
WidgetTestRunSummaryReporter(),
405-
XmlReporter(dirRoot: Directory.current.path)
406-
]
425+
..reporters = [
426+
WidgetStdoutReporter(),
427+
WidgetTestRunSummaryReporter(),
428+
XmlReporter(dirRoot: Directory.current.path)
429+
]
407430
```
408431

409432
<!--

example/android/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
gradle-wrapper.jar
2+
/.gradle
3+
/captures/
4+
/gradlew
5+
/gradlew.bat
6+
/local.properties
7+
GeneratedPluginRegistrant.java
8+
9+
# Remember to never publicly share your keystore.
10+
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11+
key.properties
12+
**/*.keystore
13+
**/*.jks

example/android/app/build.gradle

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
def localProperties = new Properties()
2+
def localPropertiesFile = rootProject.file('local.properties')
3+
if (localPropertiesFile.exists()) {
4+
localPropertiesFile.withReader('UTF-8') { reader ->
5+
localProperties.load(reader)
6+
}
7+
}
8+
9+
def flutterRoot = localProperties.getProperty('flutter.sdk')
10+
if (flutterRoot == null) {
11+
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12+
}
13+
14+
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15+
if (flutterVersionCode == null) {
16+
flutterVersionCode = '1'
17+
}
18+
19+
def flutterVersionName = localProperties.getProperty('flutter.versionName')
20+
if (flutterVersionName == null) {
21+
flutterVersionName = '1.0'
22+
}
23+
24+
apply plugin: 'com.android.application'
25+
apply plugin: 'kotlin-android'
26+
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27+
28+
android {
29+
compileSdkVersion flutter.compileSdkVersion
30+
ndkVersion flutter.ndkVersion
31+
32+
compileOptions {
33+
sourceCompatibility JavaVersion.VERSION_1_8
34+
targetCompatibility JavaVersion.VERSION_1_8
35+
}
36+
37+
kotlinOptions {
38+
jvmTarget = '1.8'
39+
}
40+
41+
sourceSets {
42+
main.java.srcDirs += 'src/main/kotlin'
43+
}
44+
45+
defaultConfig {
46+
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
47+
applicationId "com.example.example"
48+
// You can update the following values to match your application needs.
49+
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
50+
minSdkVersion flutter.minSdkVersion
51+
targetSdkVersion flutter.targetSdkVersion
52+
versionCode flutterVersionCode.toInteger()
53+
versionName flutterVersionName
54+
}
55+
56+
buildTypes {
57+
release {
58+
// TODO: Add your own signing config for the release build.
59+
// Signing with the debug keys for now, so `flutter run --release` works.
60+
signingConfig signingConfigs.debug
61+
}
62+
}
63+
}
64+
65+
flutter {
66+
source '../..'
67+
}
68+
69+
dependencies {
70+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
71+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.example.example">
3+
<!-- The INTERNET permission is required for development. Specifically,
4+
the Flutter tool needs it to communicate with the running application
5+
to allow setting breakpoints, to provide hot reload, etc.
6+
-->
7+
<uses-permission android:name="android.permission.INTERNET"/>
8+
</manifest>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.example.example">
3+
<application
4+
android:label="example"
5+
android:name="${applicationName}"
6+
android:icon="@mipmap/ic_launcher">
7+
<activity
8+
android:name=".MainActivity"
9+
android:exported="true"
10+
android:launchMode="singleTop"
11+
android:theme="@style/LaunchTheme"
12+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
13+
android:hardwareAccelerated="true"
14+
android:windowSoftInputMode="adjustResize">
15+
<!-- Specifies an Android theme to apply to this Activity as soon as
16+
the Android process has started. This theme is visible to the user
17+
while the Flutter UI initializes. After that, this theme continues
18+
to determine the Window background behind the Flutter UI. -->
19+
<meta-data
20+
android:name="io.flutter.embedding.android.NormalTheme"
21+
android:resource="@style/NormalTheme"
22+
/>
23+
<intent-filter>
24+
<action android:name="android.intent.action.MAIN"/>
25+
<category android:name="android.intent.category.LAUNCHER"/>
26+
</intent-filter>
27+
</activity>
28+
<!-- Don't delete the meta-data below.
29+
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
30+
<meta-data
31+
android:name="flutterEmbedding"
32+
android:value="2" />
33+
</application>
34+
</manifest>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.example.example
2+
3+
import io.flutter.embedding.android.FlutterActivity
4+
5+
class MainActivity: FlutterActivity() {
6+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="?android:colorBackground" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="@android:color/white" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>
544 Bytes
Loading
442 Bytes
Loading

0 commit comments

Comments
 (0)