Skip to content
This repository was archived by the owner on Mar 22, 2025. It is now read-only.

Commit ccab404

Browse files
authored
Merge pull request #125 from chornerman/release/0.5.0
Release - 0.5.0
2 parents 4b54fd5 + 9077c71 commit ccab404

File tree

76 files changed

+1382
-165
lines changed

Some content is hidden

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

76 files changed

+1382
-165
lines changed

README.md

+40-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,48 @@
1-
# survey
1+
# Survey
22

33
Nimble Flutter internal certification
44

5+
## Prerequisite
6+
7+
- Flutter 3.3
8+
- [Recommended] [Flutter Version Management (fvm)](https://fvm.app/)
9+
510
## Getting Started
611

7-
This project is a starting point for a Flutter application.
12+
### Set up the project
13+
To set up this project locally, follow the steps below:
14+
- Create `.env` files inside the project's root directory and add the required environment variables into them. Take a look at the `.env.sample` to see the list of all required environment variables
15+
- To set up the **staging** environment, create `.env.staging`
16+
- To set up the **production** environment, create `.env`
17+
- Generate Flutter files using the below command:
18+
```
19+
fvm flutter packages pub run build_runner build --delete-conflicting-outputs
20+
```
21+
22+
### Run the app
23+
24+
#### Staging
25+
To run the staging flavor app, use the below command:
26+
```
27+
fvm flutter run --flavor staging
28+
```
29+
30+
#### Production
31+
To run the production flavor app, use the below command:
32+
```
33+
fvm flutter run --flavor production
34+
```
835

9-
A few resources to get you started if this is your first Flutter project:
36+
### Run tests
1037

11-
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12-
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
38+
#### Unit tests
39+
To run all unit tests, use the below command:
40+
```
41+
fvm flutter test
42+
```
1343

14-
For help getting started with Flutter, view our
15-
[online documentation](https://flutter.dev/docs), which offers tutorials,
16-
samples, guidance on mobile development, and a full API reference.
44+
#### Integration tests
45+
To run integration tests with an emulator, use the below command:
46+
```
47+
fvm flutter drive --driver=integration_test_driver/integration_test_driver.dart --flavor staging --target=integration_test/{test_file}.dart
48+
```
+7-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
package="co.nimblehq.survey">
3-
43
<application
54
android:name="${applicationName}"
65
android:icon="@mipmap/ic_launcher"
@@ -12,25 +11,25 @@
1211
android:hardwareAccelerated="true"
1312
android:label="@string/app_name"
1413
android:launchMode="singleTop"
15-
android:screenOrientation="portrait"
1614
android:theme="@style/LaunchTheme"
17-
android:windowSoftInputMode="adjustResize">
15+
android:windowSoftInputMode="adjustResize"
16+
android:screenOrientation="portrait">
1817
<!-- Specifies an Android theme to apply to this Activity as soon as
1918
the Android process has started. This theme is visible to the user
2019
while the Flutter UI initializes. After that, this theme continues
2120
to determine the Window background behind the Flutter UI. -->
2221
<meta-data
2322
android:name="io.flutter.embedding.android.NormalTheme"
24-
android:resource="@style/NormalTheme" />
23+
android:resource="@style/NormalTheme"/>
2524
<intent-filter>
26-
<action android:name="android.intent.action.MAIN" />
27-
<category android:name="android.intent.category.LAUNCHER" />
25+
<action android:name="android.intent.action.MAIN"/>
26+
<category android:name="android.intent.category.LAUNCHER"/>
2827
</intent-filter>
2928
</activity>
3029
<!-- Don't delete the meta-data below.
3130
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
3231
<meta-data
3332
android:name="flutterEmbedding"
34-
android:value="2" />
33+
android:value="2"/>
3534
</application>
36-
</manifest>
35+
</manifest>
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<!-- Modify this file to customize your launch splash screen -->
32
<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> -->
3+
<item>
4+
<bitmap android:gravity="fill" android:src="@drawable/background"/>
5+
</item>
6+
<item>
7+
<bitmap android:gravity="center" android:src="@drawable/splash"/>
8+
</item>
129
</layer-list>
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<!-- Modify this file to customize your launch splash screen -->
32
<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> -->
3+
<item>
4+
<bitmap android:gravity="fill" android:src="@drawable/background"/>
5+
</item>
6+
<item>
7+
<bitmap android:gravity="center" android:src="@drawable/splash"/>
8+
</item>
129
</layer-list>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
4+
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
5+
<item name="android:forceDarkAllowed">false</item>
6+
<item name="android:windowFullscreen">false</item>
7+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
8+
<item name="android:windowSplashScreenBackground">#15151A</item>
9+
</style>
10+
<!-- Theme applied to the Android Window as soon as the process has started.
11+
This theme determines the color of the Android Window while your
12+
Flutter UI initializes, as well as behind your Flutter UI while its
13+
running.
14+
15+
This Theme is only used starting with V2 of Flutter's Android embedding. -->
16+
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
17+
<item name="android:windowBackground">?android:colorBackground</item>
18+
</style>
19+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
4+
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
5+
<item name="android:forceDarkAllowed">false</item>
6+
<item name="android:windowFullscreen">false</item>
7+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
8+
<item name="android:windowSplashScreenBackground">#15151A</item>
9+
</style>
10+
<!-- Theme applied to the Android Window as soon as the process has started.
11+
This theme determines the color of the Android Window while your
12+
Flutter UI initializes, as well as behind your Flutter UI while its
13+
running.
14+
15+
This Theme is only used starting with V2 of Flutter's Android embedding. -->
16+
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
17+
<item name="android:windowBackground">?android:colorBackground</item>
18+
</style>
19+
</resources>

android/app/src/main/res/values/styles.xml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
<!-- Show a splash screen on the activity. Automatically removed when
66
Flutter draws its first frame -->
77
<item name="android:windowBackground">@drawable/launch_background</item>
8+
<item name="android:forceDarkAllowed">false</item>
9+
<item name="android:windowFullscreen">false</item>
10+
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
811
</style>
912
<!-- Theme applied to the Android Window as soon as the process has started.
1013
This theme determines the color of the Android Window while your

assets/images/ic_nimble_splash.png

6.73 KB
Loading

flutter_native_splash.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
flutter_native_splash:
2+
background_image: "assets/images/bg_onboarding.png"
3+
image: assets/images/ic_nimble_splash.png
4+
android_12:
5+
color: "#15151A"
6+
android_screen_orientation: portrait
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:survey/api/request/login_request.dart';
3+
import 'package:survey/api/request/reset_password_request.dart';
4+
import 'package:survey/api/response/token_response.dart';
5+
import 'package:survey/api/service/auth_service.dart';
6+
7+
import 'fake_data.dart';
8+
9+
const loginKey = 'login';
10+
const resetPasswordKey = 'resetPassword';
11+
12+
class FakeAuthService extends Fake implements AuthService {
13+
@override
14+
Future<TokenResponse> login(LoginRequest body) async {
15+
final response = FakeData.fakeResponses[loginKey]!;
16+
17+
if (response.statusCode != successStatusCode) {
18+
throw fakeDioError(response.statusCode);
19+
}
20+
return TokenResponse.fromJson(response.json);
21+
}
22+
23+
@override
24+
Future<void> resetPassword(ResetPasswordRequest body) async {
25+
final response = FakeData.fakeResponses[resetPasswordKey]!;
26+
27+
if (response.statusCode != successStatusCode) {
28+
throw fakeDioError(response.statusCode);
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:dio/dio.dart';
2+
3+
const successStatusCode = 200;
4+
const _errorStatusCode = 400;
5+
6+
class FakeResponse {
7+
final int statusCode;
8+
final Map<String, dynamic> json;
9+
10+
FakeResponse(this.statusCode, this.json);
11+
}
12+
13+
class FakeData {
14+
FakeData._();
15+
16+
static Map<String, FakeResponse> fakeResponses = {};
17+
18+
static void addSuccessResponse(String key, Map<String, dynamic> response) {
19+
final newResponse = FakeResponse(successStatusCode, response);
20+
fakeResponses.update(key, (response) => newResponse,
21+
ifAbsent: () => newResponse);
22+
}
23+
24+
static void addErrorResponse(String key) {
25+
final newResponse = FakeResponse(_errorStatusCode, {});
26+
fakeResponses.update(key, (response) => newResponse,
27+
ifAbsent: () => newResponse);
28+
}
29+
}
30+
31+
DioError fakeDioError(int statusCode) => DioError(
32+
response: Response(
33+
statusCode: statusCode, requestOptions: RequestOptions(path: '')),
34+
type: DioErrorType.response,
35+
requestOptions: RequestOptions(path: ''),
36+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:survey/api/request/submit_survey_request.dart';
3+
import 'package:survey/api/response/survey_detail_response.dart';
4+
import 'package:survey/api/response/surveys_response.dart';
5+
import 'package:survey/api/service/survey_service.dart';
6+
7+
import 'fake_data.dart';
8+
9+
const getSurveysKey = 'getSurveys';
10+
const getSurveyDetailKey = 'getSurveyDetail';
11+
const submitSurveyKey = 'submitSurvey';
12+
13+
class FakeSurveyService extends Fake implements SurveyService {
14+
@override
15+
Future<SurveysResponse> getSurveys(int pageNumber, int pageSize) async {
16+
final response = FakeData.fakeResponses[getSurveysKey]!;
17+
18+
if (response.statusCode != successStatusCode) {
19+
throw fakeDioError(response.statusCode);
20+
}
21+
return SurveysResponse.fromJson(response.json);
22+
}
23+
24+
@override
25+
Future<SurveyDetailResponse> getSurveyDetail(String surveyId) async {
26+
final response = FakeData.fakeResponses[getSurveyDetailKey]!;
27+
28+
if (response.statusCode != successStatusCode) {
29+
throw fakeDioError(response.statusCode);
30+
}
31+
return SurveyDetailResponse.fromJson(response.json);
32+
}
33+
34+
@override
35+
Future<void> submitSurvey(SubmitSurveyRequest body) async {
36+
final response = FakeData.fakeResponses[submitSurveyKey]!;
37+
38+
if (response.statusCode != successStatusCode) {
39+
throw fakeDioError(response.statusCode);
40+
}
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:survey/api/response/user_response.dart';
3+
import 'package:survey/api/service/user_service.dart';
4+
5+
import 'fake_data.dart';
6+
7+
const getUserKey = 'getUser';
8+
9+
class FakeUserService extends Fake implements UserService {
10+
@override
11+
Future<UserResponse> getUser() async {
12+
final response = FakeData.fakeResponses[getUserKey]!;
13+
14+
if (response.statusCode != successStatusCode) {
15+
throw fakeDioError(response.statusCode);
16+
}
17+
return UserResponse.fromJson(response.json);
18+
}
19+
}

0 commit comments

Comments
 (0)