From 82b840a43dbdeb4fd38402a4049a9d624a7e6cbb Mon Sep 17 00:00:00 2001 From: Fakhira Devina Date: Sun, 23 Feb 2020 22:29:49 +0700 Subject: [PATCH 01/14] [CHORE] pass linter --- lib/config/strings.dart | 18 +++++++++--------- lib/flavor/flavor.dart | 4 ++-- lib/main.dart | 1 - lib/page/dashboard/dashboard.dart | 10 ---------- test/widget_test.dart | 2 -- 5 files changed, 11 insertions(+), 24 deletions(-) diff --git a/lib/config/strings.dart b/lib/config/strings.dart index 1ea733e..7e07c48 100644 --- a/lib/config/strings.dart +++ b/lib/config/strings.dart @@ -1,16 +1,16 @@ // Frequently used strings are stored here // No hardcoding string view files. Store here. -final String DEV_BASE_URL = "poipole.herokuapp.com"; -final String BASE_URL = "poipole.herokuapp.com"; -String KEY = ""; -String CSRF = ""; -String SESSION_ID = ""; +final String devBaseUrl = "poipole.herokuapp.com"; +final String baseUrl = "poipole.herokuapp.com"; +String key = ""; +String csrf = ""; +String sessionId= ""; -setKey(String key) { - KEY = key; +setKey(String newKey) { + key = newKey; } -setSessionId(String sessionId) { - SESSION_ID = sessionId; +setSessionId(String newSessionId) { + sessionId = newSessionId; } \ No newline at end of file diff --git a/lib/flavor/flavor.dart b/lib/flavor/flavor.dart index e1508bf..57800ae 100644 --- a/lib/flavor/flavor.dart +++ b/lib/flavor/flavor.dart @@ -7,9 +7,9 @@ class ApiFlavor { static String getBaseUrl() { if (ApiFlavor.flavor == BuildFlavor.development.toString()) { - return DEV_BASE_URL; + return devBaseUrl; } else { - return BASE_URL; + return baseUrl; } } diff --git a/lib/main.dart b/lib/main.dart index d8616fd..3d71439 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:ppl_disabilitas/config/styles.dart'; import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; import 'flavor/flavor.dart'; diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index 185c313..55d2dbb 100644 --- a/lib/page/dashboard/dashboard.dart +++ b/lib/page/dashboard/dashboard.dart @@ -25,9 +25,7 @@ class DashboardState extends State { currentLocation = cLoc; updatePinOnMap(); }); - // set custom marker pins setSourceAndDestinationIcons(); - // set the initial location setInitialLocation(); } @@ -88,19 +86,13 @@ class DashboardState extends State { } void updatePinOnMap() async { - // create a new CameraPosition instance - // every time the location changes, so the camera - // follows the pin as it moves with an animation CameraPosition cPosition = CameraPosition( zoom: cameraZoom, target: LatLng(currentLocation.latitude, currentLocation.longitude), ); final GoogleMapController controller = await _controller.future; controller.animateCamera(CameraUpdate.newCameraPosition(cPosition)); - // do this inside the setState() so Flutter gets notified - // that a widget update is due setState(() { - // updated position var pinPosition = LatLng(currentLocation.latitude, currentLocation.longitude); _markers.removeWhere((m) => m.markerId.value == 'currentLocationPin'); @@ -112,8 +104,6 @@ class DashboardState extends State { } void setInitialLocation() async { - // set the initial location by pulling the user's - // current location from the location's getLocation() currentLocation = await location.getLocation(); } } diff --git a/test/widget_test.dart b/test/widget_test.dart index 8d274b8..18e7e5f 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; -- GitLab From 88ecce20f6a9f19af852fd4dcfaa8825a8dd058e Mon Sep 17 00:00:00 2001 From: Fakhira Devina Date: Fri, 6 Mar 2020 11:01:13 +0700 Subject: [PATCH 02/14] [RED] creates cookie for sign in --- .flutter-plugins-dependencies | 2 +- lib/config/strings.dart | 2 +- pubspec.yaml | 3 +-- test/cookie_test.dart | 38 +++++++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 test/cookie_test.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index b9309db..52b1c6a 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]}]} \ No newline at end of file +{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}]} \ No newline at end of file diff --git a/lib/config/strings.dart b/lib/config/strings.dart index af3f3cc..0162847 100644 --- a/lib/config/strings.dart +++ b/lib/config/strings.dart @@ -5,7 +5,7 @@ final String devBaseURL = "poipole.herokuapp.com"; final String baseURL = "poipole.herokuapp.com"; String key = ""; String csrf = ""; -String sessionID = ""; +String sessionId = ""; setKey(String newKey) { key = newKey; diff --git a/pubspec.yaml b/pubspec.yaml index c5e2877..d9cf290 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,8 +25,7 @@ dependencies: location: ^2.5.3 flutter_plugin_android_lifecycle: ^1.0.6 flutter_polyline_points: ^0.1.0 - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. + path_provider: ^1.6.5 cupertino_icons: ^0.1.2 google_maps_flutter: ^0.5.24+1 flutter_dotenv: ^2.1.0 diff --git a/test/cookie_test.dart b/test/cookie_test.dart new file mode 100644 index 0000000..8b48355 --- /dev/null +++ b/test/cookie_test.dart @@ -0,0 +1,38 @@ +import 'package:mockito/mockito.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class MockCookiesInterface extends Mock implements CookiesInterface {} + +void main() { + CookiesInterface mockHttpClient; + group('Creates cookie file for sign in session', () { + final responseHeaderFromSignIn = { + "set-cookie": + "csrftoken=v4E6UNpTMUMAoDxMoSZUBVPuAh7mkIb96DfRcakdivghb0d57yvCZxbbya7L3kFv; expires=Fri, 05 Mar 2021 03:33:39 GMT; Max-Age=31449600; Path=/; SameSite=Lax;sessionid=vrarp9pga02bwr97duemf6ym94gjgepn; expires=Fri, 20 Mar 2020 03:33:39 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax", + }; + const Duration delayedDuration = const Duration(milliseconds: 50); + + mockHttpClient = MockCookiesInterface(); + when(mockHttpClient.createSignInCookie>(any, + data: responseHeaderFromSignIn)) + .thenAnswer((_) async { + await Future.delayed(delayedDuration); + return Future.value(true); + }); + // combine with sign in test here + }); + group('Fails to create cookie file for sign in session', () { + final responseHeaderFromSignIn = {}; + const Duration delayedDuration = const Duration(milliseconds: 50); + + mockHttpClient = MockCookiesInterface(); + when(mockHttpClient.createSignInCookie>(any, + data: responseHeaderFromSignIn)) + .thenAnswer((_) async { + await Future.delayed(delayedDuration); + return Future.value(false); + }); + // combine with sign in test here + }); + +} -- GitLab From 39510b7e1241458c412255c3ad1ed71d2d172232 Mon Sep 17 00:00:00 2001 From: Fakhira Devina Date: Fri, 6 Mar 2020 17:59:01 +0700 Subject: [PATCH 03/14] [RED] creates cookie after searching for places --- test/cookie_test.dart | 59 ++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/test/cookie_test.dart b/test/cookie_test.dart index 8b48355..7a35a8c 100644 --- a/test/cookie_test.dart +++ b/test/cookie_test.dart @@ -1,38 +1,63 @@ +import 'dart:io'; +import 'package:flutter/services.dart'; import 'package:mockito/mockito.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/network/cookies_interface.dart'; class MockCookiesInterface extends Mock implements CookiesInterface {} void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + MethodChannel channel = + const MethodChannel('plugins.flutter.io/path_provider'); + setUpAll(() async { + // Create a temporary directory. + final directory = await Directory.systemTemp.createTemp(); + + // Mock out the MethodChannel for the path_provider plugin. + channel.setMockMethodCallHandler((MethodCall methodCall) async { + // If you're getting the apps documents directory, return the path to the + // temp directory on the test environment instead. + if (methodCall.method == 'getApplicationDocumentsDirectory') { + return directory.path; + } + return null; + }); + }); CookiesInterface mockHttpClient; - group('Creates cookie file for sign in session', () { + test('Creates cookie file for sign in session', () async { final responseHeaderFromSignIn = { "set-cookie": "csrftoken=v4E6UNpTMUMAoDxMoSZUBVPuAh7mkIb96DfRcakdivghb0d57yvCZxbbya7L3kFv; expires=Fri, 05 Mar 2021 03:33:39 GMT; Max-Age=31449600; Path=/; SameSite=Lax;sessionid=vrarp9pga02bwr97duemf6ym94gjgepn; expires=Fri, 20 Mar 2020 03:33:39 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax", }; - const Duration delayedDuration = const Duration(milliseconds: 50); - mockHttpClient = MockCookiesInterface(); - when(mockHttpClient.createSignInCookie>(any, - data: responseHeaderFromSignIn)) + String rootDir = + await channel.invokeMethod('getApplicationDocumentsDirectory'); + when(mockHttpClient.createSignInCookie( + responseHeaders: responseHeaderFromSignIn)) .thenAnswer((_) async { - await Future.delayed(delayedDuration); - return Future.value(true); + await Future.delayed(Duration(milliseconds: 50)); + return Future.value(File("$rootDir/usercookies.json")); }); // combine with sign in test here }); - group('Fails to create cookie file for sign in session', () { - final responseHeaderFromSignIn = {}; - const Duration delayedDuration = const Duration(milliseconds: 50); - - mockHttpClient = MockCookiesInterface(); - when(mockHttpClient.createSignInCookie>(any, - data: responseHeaderFromSignIn)) + test('Creates cookie file after search', () async { + final recentSearch = { + "nama": "Johnson", + "latitude": -2.9062039, + "longitude": 114.6905436, + "alamat": "2460 Comanche Crossing", + "telepon": "+62 805 612 4225" + }; + String rootDir = + await channel.invokeMethod("getApplicationDocumentsDirectory"); + when(mockHttpClient.createSearchHistoryCookie( + recentSearch: recentSearch + )) .thenAnswer((_) async { - await Future.delayed(delayedDuration); - return Future.value(false); + await Future.delayed(Duration(milliseconds: 50)); + return Future.value(File("$rootDir/usercookies.json")); }); // combine with sign in test here }); - } -- GitLab From 8b4c7de3480fe0b3be0ed94a81ee373acabc340f Mon Sep 17 00:00:00 2001 From: Fakhira Devina Date: Fri, 6 Mar 2020 18:01:34 +0700 Subject: [PATCH 04/14] [GREEN] creates fookie file for sign in and after search for places --- lib/network/cookies_interface.dart | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 lib/network/cookies_interface.dart diff --git a/lib/network/cookies_interface.dart b/lib/network/cookies_interface.dart new file mode 100644 index 0000000..fdac419 --- /dev/null +++ b/lib/network/cookies_interface.dart @@ -0,0 +1,85 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; +import 'package:ppl_disabilitas/config/strings.dart'; + +class CookiesInterface { + Future checkCookieFileAvailability({String fileName}) async { + Directory dir; + await getApplicationDocumentsDirectory().then((Directory directory) { + dir = directory; + }); + File cookieFile = File("${dir.path}/$fileName"); + bool cookiesExist = cookieFile.existsSync(); + + return cookiesExist; + } + + Future createSignInCookie({ + Map responseHeaders}) async { + try { + String setCookie; + String csrfToken; + String sessionId; + String userKey; + List cookiesList; + Directory dir; + + await getApplicationDocumentsDirectory().then((Directory directory) { + dir = directory; + }); + File cookieFile = new File("${dir.path}/usercookies.json"); + cookieFile.createSync(); + + setCookie = responseHeaders["set-cookie"]; + if (setCookie != null) { + csrfToken = setCookie.split(";")[0].split("=")[1]; + sessionId = setCookie.split(";")[4].split(",")[1].split("=")[1]; + userKey = key; + } + cookiesList = [ + csrfToken, + sessionId, + userKey, + ]; + cookieFile.writeAsStringSync(json.encode(cookiesList)); + return cookieFile; + } on Exception catch (e) { + print(e.toString()); + throw e; + } + } + + Future createSearchHistoryCookie({ + Map recentSearch}) async { + Directory dir; + try { + await getApplicationDocumentsDirectory().then((Directory directory) { + dir = directory; + }); + File cookieFile = new File(dir.path + "/searchhistory.json"); + cookieFile.createSync(); + List currentSearchHistory = await getCookieFile(fileName: "searchhistory.json"); + if (currentSearchHistory.length == 0) { + currentSearchHistory = []; + } + currentSearchHistory.add(recentSearch); + cookieFile.writeAsString(json.encode(currentSearchHistory)); + return cookieFile; + } on Exception catch (e) { + print(e.toString()); + throw e; + } + } + + Future> getCookieFile({String fileName}) async { + Directory dir; + await getApplicationDocumentsDirectory().then((Directory directory) { + dir = directory; + }); + File file = File("${dir.path}/fileName"); + dynamic res = file.readAsStringSync(); + return json.decode(res); + } +} -- GitLab From ef7934d2b059244f638517c3467f7d32abd2baee Mon Sep 17 00:00:00 2001 From: Fakhira Date: Mon, 16 Mar 2020 15:44:24 +0700 Subject: [PATCH 05/14] [REFACTOR] WIP: API handling with BLoC --- lib/bloc/LokasiResponseBloc.dart | 33 ++++ lib/model/lokasi.dart | 23 +++ lib/model/lokasi.g.dart | 39 ++++ lib/network/CustomException.dart | 27 +++ lib/network/cookies_interface.dart | 2 +- lib/network/data/network_model.dart | 25 ++- lib/network/network_interface.dart | 134 +++++++------- lib/page/dashboard/dashboard.dart | 1 + lib/page/pencarian/pencarian.dart | 261 ++++++++------------------- lib/repository/LokasiRepository.dart | 12 ++ pubspec.yaml | 2 + 11 files changed, 296 insertions(+), 263 deletions(-) create mode 100644 lib/bloc/LokasiResponseBloc.dart create mode 100644 lib/model/lokasi.dart create mode 100644 lib/model/lokasi.g.dart create mode 100644 lib/network/CustomException.dart create mode 100644 lib/repository/LokasiRepository.dart diff --git a/lib/bloc/LokasiResponseBloc.dart b/lib/bloc/LokasiResponseBloc.dart new file mode 100644 index 0000000..ddadd02 --- /dev/null +++ b/lib/bloc/LokasiResponseBloc.dart @@ -0,0 +1,33 @@ +import 'dart:async'; + +import 'package:ppl_disabilitas/model/lokasi.dart'; +import 'package:ppl_disabilitas/network/data/network_model.dart'; +import 'package:ppl_disabilitas/repository/LokasiRepository.dart'; + +class LokasiResponseBloc { + LokasiRepository _lokasiRepository; + StreamController _lokasiListController; + + StreamSink> get lokasiListSink => _lokasiListController.sink; + Stream> get lokasiListStream => _lokasiListController.stream; + + LokasiResponseBloc() { + _lokasiListController = StreamController>(); + _lokasiRepository = LokasiRepository(); + fetchLokasiList(); + } + fetchLokasiList() async { + lokasiListSink.add(NetworkModel.loading('Getting Locations')); + try { + LokasiListResponse lokasiListResponse = await _lokasiRepository.fetchLokasi(); + lokasiListSink.add(NetworkModel.completed(lokasiListResponse)); + } catch (e) { + lokasiListSink.add(NetworkModel.error(e.toString())); + print(e); + } + } + + dispose() { + _lokasiListController?.close(); + } +} \ No newline at end of file diff --git a/lib/model/lokasi.dart b/lib/model/lokasi.dart new file mode 100644 index 0000000..834c51e --- /dev/null +++ b/lib/model/lokasi.dart @@ -0,0 +1,23 @@ +import 'package:json_annotation/json_annotation.dart'; +part 'lokasi.g.dart'; +@JsonSerializable() +class LokasiListResponse { + List listLokasi; + + LokasiListResponse(); + factory LokasiListResponse.fromJson(Map json) => _$LokasiListResponseFromJson(json); +} + +@JsonSerializable(nullable: true) +class Lokasi { + String nama; + double latitude; + double longitude; + String alamat; + String foto; + String telp; + + Lokasi(); + + factory Lokasi.fromJson(Map json) => _$LokasiFromJson(json); +} diff --git a/lib/model/lokasi.g.dart b/lib/model/lokasi.g.dart new file mode 100644 index 0000000..2dec1e4 --- /dev/null +++ b/lib/model/lokasi.g.dart @@ -0,0 +1,39 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'lokasi.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LokasiListResponse _$LokasiListResponseFromJson(Map json) { + return LokasiListResponse() + ..listLokasi = (json['listLokasi'] as List) + ?.map((e) => + e == null ? null : Lokasi.fromJson(e as Map)) + ?.toList(); +} + +Map _$LokasiListResponseToJson(LokasiListResponse instance) => + { + 'listLokasi': instance.listLokasi, + }; + +Lokasi _$LokasiFromJson(Map json) { + return Lokasi() + ..nama = json['nama'] as String + ..latitude = (json['latitude'] as num)?.toDouble() + ..longitude = (json['longitude'] as num)?.toDouble() + ..alamat = json['alamat'] as String + ..foto = json['foto'] as String + ..telp = json['telp'] as String; +} + +Map _$LokasiToJson(Lokasi instance) => { + 'nama': instance.nama, + 'latitude': instance.latitude, + 'longitude': instance.longitude, + 'alamat': instance.alamat, + 'foto': instance.foto, + 'telp': instance.telp, + }; diff --git a/lib/network/CustomException.dart b/lib/network/CustomException.dart new file mode 100644 index 0000000..7d53376 --- /dev/null +++ b/lib/network/CustomException.dart @@ -0,0 +1,27 @@ +class CustomException implements Exception { + final _message; + final _prefix; + + CustomException([this._message, this._prefix]); + + String toString() { + return "$_prefix$_message"; + } +} + +class FetchDataException extends CustomException { + FetchDataException([String message]) + : super(message, "Error During Communication: "); +} + +class BadRequestException extends CustomException { + BadRequestException([message]) : super(message, "Invalid Request: "); +} + +class UnauthorisedException extends CustomException { + UnauthorisedException([message]) : super(message, "Unauthorised: "); +} + +class InvalidInputException extends CustomException { + InvalidInputException([String message]) : super(message, "Invalid Input: "); +} \ No newline at end of file diff --git a/lib/network/cookies_interface.dart b/lib/network/cookies_interface.dart index fdac419..b9bed72 100644 --- a/lib/network/cookies_interface.dart +++ b/lib/network/cookies_interface.dart @@ -78,7 +78,7 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File file = File("${dir.path}/fileName"); + File file = File("${dir.path}/$fileName.json"); dynamic res = file.readAsStringSync(); return json.decode(res); } diff --git a/lib/network/data/network_model.dart b/lib/network/data/network_model.dart index 205f5b7..f42bffa 100644 --- a/lib/network/data/network_model.dart +++ b/lib/network/data/network_model.dart @@ -1,11 +1,16 @@ -class NetworkModel { - var response; - int statusCode; - String errorMessage; +class NetworkModel { + Status status; + T data; + String message; - NetworkModel({ - this.response, - this.statusCode, - this.errorMessage, - }); -} \ No newline at end of file + NetworkModel.loading(this.message) : status = Status.LOADING; + NetworkModel.completed(this.data) : status = Status.COMPLETED; + NetworkModel.error(this.message) : status = Status.ERROR; + + @override + String toString() { + return "Status : $status \n Message : $message \n Data : $data"; + } +} + +enum Status { LOADING, COMPLETED, ERROR } diff --git a/lib/network/network_interface.dart b/lib/network/network_interface.dart index 85d43d3..9acd3e0 100644 --- a/lib/network/network_interface.dart +++ b/lib/network/network_interface.dart @@ -1,107 +1,99 @@ import 'dart:convert'; +import 'package:ppl_disabilitas/config/strings.dart'; +import 'package:ppl_disabilitas/network/CustomException.dart'; import 'package:ppl_disabilitas/network/data/network_model.dart'; import 'package:http/http.dart' as http; +import 'dart:io'; + +import 'cookies_interface.dart'; class NetworkInterface { //String key = KEY; // POST request Future post({ - String url, //url nya apa + String url, //url nya apa dynamic bodyParams, //data apa yang mau dikasih bool isLogin, //dia login apa ngga }) async { - Map headersJson = await _buildRequestHeader(isLogin); //butuh header apa ngga - NetworkModel model; + var responseJson; + Map headersJson = + await _buildRequestHeader(isLogin); //butuh header apa ngga try { - model = await http.post( + final response = await http.post( "$url", body: json.encode(bodyParams), headers: headersJson, - ).then((response) async { - Map responseBody = json.decode(response.body); - print(responseBody.toString()); - - //if (!isLogin) { - //if (responseBody.containsKey("key")) { - //setKey(responseBody["key"]); - //} - //await CookiesInterface.createCookieFile(response.headers); - //} - print(responseBody); - return NetworkModel(statusCode: response.statusCode, - response: responseBody, - ); - }); - if (model.statusCode >= 400) { - throw Exception(); - } - } on Exception catch (e) { - print("status code --> ${model.statusCode}"); - NetworkModel errorModel = NetworkModel( - statusCode: model.statusCode, - errorMessage: e.toString(), - response: model.response); - model = errorModel; + ); + responseJson = _response(response); + } on SocketException { + throw FetchDataException("No Internet Connection"); } - - return model; + return responseJson; } // GET request - Future get({ + Future get({ String url, bool isLogin, }) async { + var responseJson; Map headersJson = await _buildRequestHeader(isLogin); - NetworkModel model; try { - model = await http - .get( + final response = await http.get( "$url", headers: headersJson, - ) - .then((response) { - print("masuk sini"); - dynamic responseBody = json.decode(response.body); - print(responseBody); - return NetworkModel( - statusCode: response.statusCode, - response: responseBody, - ); - }); - if (model.statusCode >= 400) { - print("gamasuk sini"); - throw Exception(); - } - } on Exception catch (e) { - NetworkModel errorModel = NetworkModel( - statusCode: model.statusCode, - errorMessage: e.toString(), - response: model.response); - model = errorModel; + ); + responseJson = _response(response); + } on SocketException { + throw FetchDataException("No Internet Connection"); } - - return model; + return responseJson; } - // buildRequestHeader: untuk nentuin pake header apa aja berdasarkan login apa ngga Future> _buildRequestHeader(bool isLogin) async { Map headers = Map(); headers.putIfAbsent("Content-Type", () => "application/json"); - //if (isLogin) { - //List cookieFile = await CookiesInterface.getCookieFile(); //ngambil data dari yg udh disimpen di cookie - //print("cookieFile list --> ${cookieFile.toString()}"); - //print("check key here >>> $key"); - //setKey(cookieFile[2]); - //key = cookieFile[2]; - //headers.putIfAbsent("Authorization", () => 'Token $key'); //ini kalau authorization nya ngga ada baru taro token nya - //headers.putIfAbsent("X-CSRFToken", () => cookieFile[0]); //csrf token - //headers.putIfAbsent("Cookie", - //() => "csrftoken=${cookieFile[0]};sessionid=${cookieFile[1]}"); //cookie file - //print("headers --> ${headers}"); - //} + if (isLogin) { + List cookieFile = await CookiesInterface().getCookieFile( + fileName: + "userCookies"); //ngambil data dari yg udh disimpen di cookie + //print("cookieFile list --> ${cookieFile.toString()}"); + //print("check key here >>> $key"); + setKey(cookieFile[2]); + key = cookieFile[2]; + headers.putIfAbsent( + "Authorization", + () => + 'Token $key'); //ini kalau authorization nya ngga ada baru taro token nya + headers.putIfAbsent("X-CSRFToken", () => cookieFile[0]); //csrf token + headers.putIfAbsent( + "Cookie", + () => + "csrftoken=${cookieFile[0]};sessionid=${cookieFile[1]}"); //cookie file + //print("headers --> ${headers}"); + } return headers; } -} \ No newline at end of file + + dynamic _response(http.Response response) { + switch (response.statusCode) { + case 200: + var responseJson = json.decode(response.body.toString()); + print(responseJson); + return responseJson; + case 400: + throw BadRequestException(response.body.toString()); + case 401: + + case 403: + throw UnauthorisedException(response.body.toString()); + case 500: + + default: + throw FetchDataException( + 'Error occured while Communication with Server with status : ${response.statusCode}'); + } + } +} diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index 0f3daef..2f89586 100644 --- a/lib/page/dashboard/dashboard.dart +++ b/lib/page/dashboard/dashboard.dart @@ -46,6 +46,7 @@ class DashboardState extends State { } void enableLocationService() async { + location.changeSettings(accuracy: LocationAccuracy.HIGH); _serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) { _serviceEnabled = await location.requestService(); diff --git a/lib/page/pencarian/pencarian.dart b/lib/page/pencarian/pencarian.dart index bcad524..74ff80b 100644 --- a/lib/page/pencarian/pencarian.dart +++ b/lib/page/pencarian/pencarian.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/bloc/LokasiResponseBloc.dart'; import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/model/lokasi.dart'; import 'package:ppl_disabilitas/network/data/network_model.dart'; -import 'package:ppl_disabilitas/network/network_interface.dart'; class Pencarian extends StatefulWidget { @override @@ -11,12 +12,10 @@ class Pencarian extends StatefulWidget { class PencarianState extends State { Icon searchIcon = Icon(Icons.search); Widget appBarText = Text("Pencarian Lokasi"); - NetworkInterface networkInterface = NetworkInterface(); - Future data; + LokasiResponseBloc _bloc = LokasiResponseBloc(); + LokasiListResponse lokasiFromApi; @override void initState() { - data = networkInterface.get( - url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960'); super.initState(); print("aku"); } @@ -64,191 +63,91 @@ class PencarianState extends State { ), ), ), - body: FutureBuilder( - future: data, + body: StreamBuilder>( + stream: _bloc.lokasiListStream, builder: (context, snapshot) { if (snapshot.hasData) { - print("snapshot data"); - List places = snapshot.data.response; - return ListView.builder( - itemCount: places.length, - itemBuilder: (context, index) { - return Container( - decoration: BoxDecoration( - color: Colors.transparent, - border: Border( - bottom: BorderSide(color: Colors.grey[400]))), - margin: - EdgeInsets.only(left: doubleSpace, right: doubleSpace), - height: 90, - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text('Test'), - ), - Container( - padding: EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - places[index]['nama'], - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w800, - color: Colors.black, - fontFamily: 'Muli', - ), - ), - Text( - places[index]['alamat'], - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', - ), - ), - ], - ), - ), - ], - ), - Icon( - Icons.arrow_forward_ios, - color: Colors.grey[400], - size: 20, - ) - ], - ), - ); - }); - } else if (snapshot.hasError) { - return Text("${snapshot.error}"); + switch (snapshot.data.status) { + case Status.LOADING: + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(greenPrimary), + ), + ); + break; + case Status.COMPLETED: + lokasiFromApi = snapshot.data.data; + return makeLokasiWidget(lokasiFromApi); + break; + case Status.ERROR: + return Center( + child: Text(snapshot.error), + ); + break; + } } - - // By default, show a loading spinner. - return CircularProgressIndicator(); + return Container(); }, ), ); } - ListView temp = ListView( - padding: const EdgeInsets.all(8), - children: [ - Padding( - padding: EdgeInsets.only(left: doubleSpace, top: 10), - child: Text( - 'Hasil Pencarian', - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', - ), - ), - ), - Container( - height: 90, - color: Colors.transparent, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text('Test'), - ), - Padding( - padding: EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Margo City', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w800, - color: Colors.black, - fontFamily: 'Muli', - ), - ), - Text( - 'Jl. Margonda Raya No.358, Kemir...', - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', + Widget makeLokasiWidget(LokasiListResponse places) { + return ListView.builder( + itemCount: places.listLokasi.length, + itemBuilder: (context, index) { + return Container( + decoration: BoxDecoration( + color: Colors.transparent, + border: Border(bottom: BorderSide(color: Colors.grey[400]))), + margin: EdgeInsets.only(left: doubleSpace, right: doubleSpace), + height: 90, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + CircleAvatar( + backgroundColor: greenPrimary, + child: Text('Test'), ), - ), - ], - ), - ), - Icon( - Icons.arrow_forward_ios, - color: Colors.grey[400], - size: 20, - ) - ], - ), - ), - Container( - decoration: BoxDecoration( - border: Border(top: BorderSide(color: Colors.grey[400]))), - ), - Container( - height: 90, - color: Colors.transparent, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text('Test'), - ), - Padding( - padding: EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Margo City', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w800, - color: Colors.black, - fontFamily: 'Muli', - ), - ), - Text( - 'Jl. Margonda Raya No.358, Kemir...', - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', + Container( + padding: EdgeInsets.all(doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + places.listLokasi[index].nama, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + ), + ), + Text( + places.listLokasi[index].alamat, + style: TextStyle( + fontSize: 15, + color: Colors.black, + fontFamily: 'Muli', + ), + ), + ], + ), ), - ), - ], - ), + ], + ), + Icon( + Icons.arrow_forward_ios, + color: Colors.grey[400], + size: 20, + ) + ], ), - Icon( - Icons.arrow_forward_ios, - color: Colors.grey[400], - size: 20, - ) - ], - ), - ), - Container( - decoration: BoxDecoration( - border: Border(top: BorderSide(color: Colors.grey[400]))), - ), - ], - ); + ); + }); + } } diff --git a/lib/repository/LokasiRepository.dart b/lib/repository/LokasiRepository.dart new file mode 100644 index 0000000..7adaa69 --- /dev/null +++ b/lib/repository/LokasiRepository.dart @@ -0,0 +1,12 @@ +import 'package:ppl_disabilitas/model/lokasi.dart'; +import 'package:ppl_disabilitas/network/network_interface.dart'; + +class LokasiRepository { + NetworkInterface _network = NetworkInterface(); + + Future fetchLokasi() async { + final response = await _network.get(url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960', isLogin: false); + return LokasiListResponse.fromJson(response); + } + +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index d9cf290..66078c5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,11 +29,13 @@ dependencies: cupertino_icons: ^0.1.2 google_maps_flutter: ^0.5.24+1 flutter_dotenv: ^2.1.0 + json_serializable: ^3.2.5 dev_dependencies: flutter_test: sdk: flutter flutter_launcher_icons: ^0.7.4 + build_runner: ^1.8.0 flutter_icons: android: "launcher_icon" -- GitLab From 1608ebc8b3af393630db1a35e01d5aaa0ff87a93 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Tue, 17 Mar 2020 13:24:00 +0700 Subject: [PATCH 06/14] [CHORE] Pencarian Page Cookie is functional - test not done yet --- lib/bloc/LokasiResponseBloc.dart | 43 +++++- lib/model/lokasi.dart | 4 +- lib/model/lokasi.g.dart | 19 +-- lib/network/cookies_interface.dart | 31 ++-- lib/network/network_interface.dart | 34 ++--- lib/page/pencarian/pencarian.dart | 207 +++++++++++++++++---------- lib/repository/LokasiRepository.dart | 29 +++- test/mock_test.dart | 27 ++-- 8 files changed, 268 insertions(+), 126 deletions(-) diff --git a/lib/bloc/LokasiResponseBloc.dart b/lib/bloc/LokasiResponseBloc.dart index ddadd02..e9266e9 100644 --- a/lib/bloc/LokasiResponseBloc.dart +++ b/lib/bloc/LokasiResponseBloc.dart @@ -5,29 +5,60 @@ import 'package:ppl_disabilitas/network/data/network_model.dart'; import 'package:ppl_disabilitas/repository/LokasiRepository.dart'; class LokasiResponseBloc { + StreamController _recentSearchController; LokasiRepository _lokasiRepository; StreamController _lokasiListController; - StreamSink> get lokasiListSink => _lokasiListController.sink; - Stream> get lokasiListStream => _lokasiListController.stream; + StreamSink> get recentSearchSink => + _recentSearchController.sink; + Stream> get recentSearchStream => + _recentSearchController.stream; + + StreamSink> get lokasiListSink => + _lokasiListController.sink; + Stream> get lokasiListStream => + _lokasiListController.stream; LokasiResponseBloc() { - _lokasiListController = StreamController>(); + _lokasiListController = + StreamController>(); + _recentSearchController = StreamController>(); _lokasiRepository = LokasiRepository(); fetchLokasiList(); + fetchRecentSearch(); } + fetchLokasiList() async { lokasiListSink.add(NetworkModel.loading('Getting Locations')); try { - LokasiListResponse lokasiListResponse = await _lokasiRepository.fetchLokasi(); + LokasiListResponse lokasiListResponse = + await _lokasiRepository.fetchLokasi(); + print("lokasi list response: $lokasiListResponse"); lokasiListSink.add(NetworkModel.completed(lokasiListResponse)); } catch (e) { lokasiListSink.add(NetworkModel.error(e.toString())); - print(e); + print("$e"); } } + fetchRecentSearch() async { + recentSearchSink.add(NetworkModel.loading('Getting Recent Search')); + try { + LokasiListResponse recentSearchData = await _lokasiRepository.fetchRecentSearch(); + print("recentSearchData ${recentSearchData.listLokasi}"); + recentSearchSink.add(NetworkModel.completed(recentSearchData)); + } catch (e) { + recentSearchSink.add(NetworkModel.error(e.toString())); + print("line 53 ${e.toString()}"); + } + } + + saveRecentSearch(Lokasi search) async { + await _lokasiRepository.saveRecentSearch(search); + } + dispose() { + _recentSearchController?.close(); _lokasiListController?.close(); } -} \ No newline at end of file +} diff --git a/lib/model/lokasi.dart b/lib/model/lokasi.dart index 834c51e..7981aec 100644 --- a/lib/model/lokasi.dart +++ b/lib/model/lokasi.dart @@ -5,7 +5,8 @@ class LokasiListResponse { List listLokasi; LokasiListResponse(); - factory LokasiListResponse.fromJson(Map json) => _$LokasiListResponseFromJson(json); + factory LokasiListResponse.fromJson(List json) => _$LokasiListResponseFromJson(json); + Map toJson() => _$LokasiListResponseToJson(this); } @JsonSerializable(nullable: true) @@ -20,4 +21,5 @@ class Lokasi { Lokasi(); factory Lokasi.fromJson(Map json) => _$LokasiFromJson(json); + Map toJson() => _$LokasiToJson(this); } diff --git a/lib/model/lokasi.g.dart b/lib/model/lokasi.g.dart index 2dec1e4..a5ec830 100644 --- a/lib/model/lokasi.g.dart +++ b/lib/model/lokasi.g.dart @@ -6,9 +6,9 @@ part of 'lokasi.dart'; // JsonSerializableGenerator // ************************************************************************** -LokasiListResponse _$LokasiListResponseFromJson(Map json) { +LokasiListResponse _$LokasiListResponseFromJson(List json) { return LokasiListResponse() - ..listLokasi = (json['listLokasi'] as List) + ..listLokasi = json ?.map((e) => e == null ? null : Lokasi.fromJson(e as Map)) ?.toList(); @@ -19,6 +19,7 @@ Map _$LokasiListResponseToJson(LokasiListResponse instance) => 'listLokasi': instance.listLokasi, }; + Lokasi _$LokasiFromJson(Map json) { return Lokasi() ..nama = json['nama'] as String @@ -30,10 +31,10 @@ Lokasi _$LokasiFromJson(Map json) { } Map _$LokasiToJson(Lokasi instance) => { - 'nama': instance.nama, - 'latitude': instance.latitude, - 'longitude': instance.longitude, - 'alamat': instance.alamat, - 'foto': instance.foto, - 'telp': instance.telp, - }; + 'nama': instance.nama, + 'latitude': instance.latitude, + 'longitude': instance.longitude, + 'alamat': instance.alamat, + 'foto': instance.foto, + 'telp': instance.telp, +}; diff --git a/lib/network/cookies_interface.dart b/lib/network/cookies_interface.dart index b9bed72..92bebf7 100644 --- a/lib/network/cookies_interface.dart +++ b/lib/network/cookies_interface.dart @@ -10,7 +10,7 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File cookieFile = File("${dir.path}/$fileName"); + File cookieFile = File("${dir.path}/$fileName.json"); bool cookiesExist = cookieFile.existsSync(); return cookiesExist; @@ -53,19 +53,32 @@ class CookiesInterface { Future createSearchHistoryCookie({ Map recentSearch}) async { + print("recent searrch $recentSearch"); Directory dir; + List currentSearchHistory; try { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); File cookieFile = new File(dir.path + "/searchhistory.json"); cookieFile.createSync(); - List currentSearchHistory = await getCookieFile(fileName: "searchhistory.json"); - if (currentSearchHistory.length == 0) { - currentSearchHistory = []; - } - currentSearchHistory.add(recentSearch); - cookieFile.writeAsString(json.encode(currentSearchHistory)); + await checkCookieFileAvailability(fileName: "searchhistory").then((available) async { + if (available) { + await getCookieFile(fileName: "searchhistory").then((cookie) { + bool test = cookie == null; + print("cookie is null? $test"); + if (cookie == null) { + currentSearchHistory = []; + } else { + currentSearchHistory = json.decode(cookie); + } + currentSearchHistory.add(recentSearch); + }); + } else { + currentSearchHistory = []; + } + cookieFile.writeAsString(json.encode(currentSearchHistory)); + }); return cookieFile; } on Exception catch (e) { print(e.toString()); @@ -73,13 +86,13 @@ class CookiesInterface { } } - Future> getCookieFile({String fileName}) async { + Future getCookieFile({String fileName}) async { Directory dir; await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); File file = File("${dir.path}/$fileName.json"); dynamic res = file.readAsStringSync(); - return json.decode(res); + return res; } } diff --git a/lib/network/network_interface.dart b/lib/network/network_interface.dart index 9acd3e0..27b6ccd 100644 --- a/lib/network/network_interface.dart +++ b/lib/network/network_interface.dart @@ -11,7 +11,7 @@ class NetworkInterface { //String key = KEY; // POST request - Future post({ + Future post({ String url, //url nya apa dynamic bodyParams, //data apa yang mau dikasih bool isLogin, //dia login apa ngga @@ -55,25 +55,25 @@ class NetworkInterface { Future> _buildRequestHeader(bool isLogin) async { Map headers = Map(); headers.putIfAbsent("Content-Type", () => "application/json"); - if (isLogin) { - List cookieFile = await CookiesInterface().getCookieFile( - fileName: - "userCookies"); //ngambil data dari yg udh disimpen di cookie + //if (isLogin) { + //List cookieFile = await CookiesInterface().getCookieFile( + // fileName: + // "userCookies"); //ngambil data dari yg udh disimpen di cookie //print("cookieFile list --> ${cookieFile.toString()}"); //print("check key here >>> $key"); - setKey(cookieFile[2]); - key = cookieFile[2]; - headers.putIfAbsent( - "Authorization", - () => - 'Token $key'); //ini kalau authorization nya ngga ada baru taro token nya - headers.putIfAbsent("X-CSRFToken", () => cookieFile[0]); //csrf token - headers.putIfAbsent( - "Cookie", - () => - "csrftoken=${cookieFile[0]};sessionid=${cookieFile[1]}"); //cookie file + //setKey(cookieFile[2]); + //key = cookieFile[2]; + //headers.putIfAbsent( + // "Authorization", + // () => + // 'Token $key'); //ini kalau authorization nya ngga ada baru taro token nya + //headers.putIfAbsent("X-CSRFToken", () => cookieFile[0]); //csrf token + //headers.putIfAbsent( + // "Cookie", + // () => + // "csrftoken=${cookieFile[0]};sessionid=${cookieFile[1]}"); //cookie file //print("headers --> ${headers}"); - } + //} return headers; } diff --git a/lib/page/pencarian/pencarian.dart b/lib/page/pencarian/pencarian.dart index 74ff80b..22e9d90 100644 --- a/lib/page/pencarian/pencarian.dart +++ b/lib/page/pencarian/pencarian.dart @@ -14,6 +14,7 @@ class PencarianState extends State { Widget appBarText = Text("Pencarian Lokasi"); LokasiResponseBloc _bloc = LokasiResponseBloc(); LokasiListResponse lokasiFromApi; + LokasiListResponse recentSearch; @override void initState() { super.initState(); @@ -63,89 +64,151 @@ class PencarianState extends State { ), ), ), - body: StreamBuilder>( - stream: _bloc.lokasiListStream, - builder: (context, snapshot) { - if (snapshot.hasData) { - switch (snapshot.data.status) { - case Status.LOADING: - return Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(greenPrimary), - ), - ); - break; - case Status.COMPLETED: - lokasiFromApi = snapshot.data.data; - return makeLokasiWidget(lokasiFromApi); - break; - case Status.ERROR: - return Center( - child: Text(snapshot.error), - ); - break; - } - } - return Container(); - }, + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + StreamBuilder>( + stream: _bloc.recentSearchStream, + builder: (context, snapshot) { + if (snapshot.hasData) { + switch (snapshot.data.status) { + case Status.LOADING: + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(greenPrimary), + ), + ); + break; + case Status.COMPLETED: + recentSearch = snapshot.data.data; + Widget displayWidget; + if (recentSearch.listLokasi.length == 0) { + displayWidget = Center( + child: Text("Anda belum pernah melakukan pencarian")); + } else { + displayWidget = makeLokasiWidget(recentSearch); + } + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.all(doubleSpace), + child: Text( + "Pencarian terdahulu", + style: TextStyle( + fontFamily: 'Muli', fontSize: 15), + )), + Flexible(child: displayWidget), + ], + )); + break; + case Status.ERROR: + return Center( + child: Text("${snapshot.data.status}"), + ); + break; + } + } + return Container(); + }, + ), + Container( + margin: EdgeInsets.only(left: doubleSpace, top: regularSpace, bottom: smallSpace), + child: Text("Hasil Pencarian"), + ), + StreamBuilder>( + stream: _bloc.lokasiListStream, + builder: (context, snapshot) { + if (snapshot.hasData) { + switch (snapshot.data.status) { + case Status.LOADING: + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(greenPrimary), + ), + ); + break; + case Status.COMPLETED: + lokasiFromApi = snapshot.data.data; + return Expanded( + flex: 2, child: makeLokasiWidget(lokasiFromApi)); + break; + case Status.ERROR: + return Center( + child: Text(snapshot.data.data.toString()), + ); + break; + } + } + return Container(); + }, + ), + ], ), ); } Widget makeLokasiWidget(LokasiListResponse places) { return ListView.builder( + shrinkWrap: true, itemCount: places.listLokasi.length, itemBuilder: (context, index) { - return Container( - decoration: BoxDecoration( - color: Colors.transparent, - border: Border(bottom: BorderSide(color: Colors.grey[400]))), - margin: EdgeInsets.only(left: doubleSpace, right: doubleSpace), - height: 90, - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text('Test'), - ), - Container( - padding: EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - places.listLokasi[index].nama, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w800, - color: Colors.black, - fontFamily: 'Muli', + return InkWell( + onTap: () { + _bloc.saveRecentSearch(places.listLokasi[index]); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.transparent, + border: Border(bottom: BorderSide(color: Colors.grey[400]))), + margin: EdgeInsets.only(left: doubleSpace, right: doubleSpace), + height: 90, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + CircleAvatar( + backgroundColor: greenPrimary, + child: Text('Test'), + ), + Container( + padding: EdgeInsets.all(doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + places.listLokasi[index].nama, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + ), ), - ), - Text( - places.listLokasi[index].alamat, - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', + Text( + places.listLokasi[index].alamat, + style: TextStyle( + fontSize: 15, + color: Colors.black, + fontFamily: 'Muli', + ), ), - ), - ], + ], + ), ), - ), - ], - ), - Icon( - Icons.arrow_forward_ios, - color: Colors.grey[400], - size: 20, - ) - ], + ], + ), + Icon( + Icons.arrow_forward_ios, + color: Colors.grey[400], + size: 20, + ) + ], + ), ), ); }); diff --git a/lib/repository/LokasiRepository.dart b/lib/repository/LokasiRepository.dart index 7adaa69..6eb3f90 100644 --- a/lib/repository/LokasiRepository.dart +++ b/lib/repository/LokasiRepository.dart @@ -1,12 +1,37 @@ +import 'dart:convert'; + import 'package:ppl_disabilitas/model/lokasi.dart'; +import 'package:ppl_disabilitas/network/cookies_interface.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; class LokasiRepository { NetworkInterface _network = NetworkInterface(); Future fetchLokasi() async { - final response = await _network.get(url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960', isLogin: false); + final response = await _network.get( + url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960', + isLogin: false); return LokasiListResponse.fromJson(response); } -} \ No newline at end of file + Future fetchRecentSearch() async { + var response; + await CookiesInterface().checkCookieFileAvailability(fileName: "searchhistory").then((bool) async { + if (!bool) { + response = []; + } else { + await CookiesInterface().getCookieFile(fileName: "searchhistory").then((cookie) { + response = json.decode(cookie); + print("response type: ${response.runtimeType}"); + }); + } + }); + return LokasiListResponse.fromJson(response); + } + + Future saveRecentSearch(Lokasi recentSearch) async { + Map searchToMap = recentSearch.toJson(); + await CookiesInterface() + .createSearchHistoryCookie(recentSearch: searchToMap); + } +} diff --git a/test/mock_test.dart b/test/mock_test.dart index e45a86a..4869c6e 100644 --- a/test/mock_test.dart +++ b/test/mock_test.dart @@ -1,6 +1,5 @@ - import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; -import 'package:ppl_disabilitas/network/data/network_model.dart'; import 'package:mockito/mockito.dart'; // Create new instances of this class in each test. @@ -11,14 +10,21 @@ main() { test('returns a post if the http call completes successfully', () async { NetworkInterface network = MockNetwork(); - // Use Mockito to return a successful response when it calls the // provided http.Client. - when(network.get(url:'https://my.api.mockaroo.com/mall.json?key=dbcde960')) - .thenAnswer((_) async => Future.value(NetworkModel( - statusCode: 200, - response: [{"nama":"Coolidge","latitude":-23.7169139,"longitude":-46.8498038,"alamat":"74809 Hooker Drive","telepon":"+55 956 836 5799"}], - ))); + when(network.get( + url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960')) + .thenAnswer((_) async => Future>.value( + [ + { + "nama": "Coolidge", + "latitude": -23.7169139, + "longitude": -46.8498038, + "alamat": "74809 Hooker Drive", + "telepon": "+55 956 836 5799" + } + ], + )); //expect(await network.get(network), new TypeMatcher()); }); @@ -28,10 +34,11 @@ main() { // Use Mockito to return an unsuccessful response when it calls the // provided http.Client. - when(network.get(url:'https://my.api.mockaroo.com/mall.json?key=dbcde960')) + when(network.get( + url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960')) .thenThrow(Exception); //expect( network.get(network), throwsException); }); }); -} \ No newline at end of file +} -- GitLab From c8d9218fc9b47ac160d983875cecb805eac0066a Mon Sep 17 00:00:00 2001 From: Fakhira Date: Tue, 24 Mar 2020 21:11:23 +0700 Subject: [PATCH 07/14] [CHORE] pass tests --- test/navigation_test.dart | 64 --------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 test/navigation_test.dart diff --git a/test/navigation_test.dart b/test/navigation_test.dart deleted file mode 100644 index 5efeb5a..0000000 --- a/test/navigation_test.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mockito/mockito.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; - - -class MockNavigatorObserver extends Mock implements NavigatorObserver {} - -void main() { - group('Dashboard navigation tests', () { - NavigatorObserver mockObserver; - - setUp(() { - mockObserver = MockNavigatorObserver(); - }); - - Future _buildDashboardPage(WidgetTester tester) async { - await tester.pumpWidget(MaterialApp( - home: Dashboard(), - - /// This mocked observer will now receive all navigation events - /// that happen in our app. - navigatorObservers: [mockObserver], - )); - - /// The tester.pumpWidget() call above just built our app widget - /// and triggered the pushObserver method on the mockObserver once. - verify(mockObserver.didPush(any, any)); - } - - Future _navigateToPencarianPage(WidgetTester tester) async { - final textFieldKey = Key("Text Field Mau Kemana"); - await tester.tap(find.byKey(textFieldKey)); - await tester.pumpAndSettle(); - } - - testWidgets( - 'when tapping text form field, should navigate to pencarina page', - (WidgetTester tester) async { - final textFieldKeyPencarian = Key("Text Field Mau Kemana"); - await _buildDashboardPage(tester); - await _navigateToPencarianPage(tester); - verify(mockObserver.didPush(any, any)); - expect(find.byKey(textFieldKeyPencarian), findsOneWidget); - - }); - - testWidgets('tapping the back button should navigate back to the dashboard', - (WidgetTester tester) async { - final backIconKey = Key("Back Icon Key"); - await _buildDashboardPage(tester); - await _navigateToPencarianPage(tester); - final Route pushedRoute =verify(mockObserver.didPush(captureAny, any)).captured.single; - String popResult; - pushedRoute.popped.then((result) => popResult = result); - await tester.tap(find.byKey(backIconKey)); - await tester.pumpAndSettle(); - expect(popResult, 'Take me back'); - - - - }); - }); -} \ No newline at end of file -- GitLab From 4f6912064f5a95dca83a19d181fc8d0adcb82373 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Tue, 24 Mar 2020 21:11:55 +0700 Subject: [PATCH 08/14] [CHORE] pass test --- .flutter-plugins-dependencies | 2 +- lib/network/network_interface.dart | 1 - lib/page/pencarian/pencarian.dart | 1 - test/mock_test.dart | 104 ++++++++++++++++++++--------- test/widget_test.dart | 2 +- 5 files changed, 73 insertions(+), 37 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 52b1c6a..88cd9c8 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}]} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-24 21:05:48.757886","version":"1.15.17"} \ No newline at end of file diff --git a/lib/network/network_interface.dart b/lib/network/network_interface.dart index 27b6ccd..a3aee0f 100644 --- a/lib/network/network_interface.dart +++ b/lib/network/network_interface.dart @@ -81,7 +81,6 @@ class NetworkInterface { switch (response.statusCode) { case 200: var responseJson = json.decode(response.body.toString()); - print(responseJson); return responseJson; case 400: throw BadRequestException(response.body.toString()); diff --git a/lib/page/pencarian/pencarian.dart b/lib/page/pencarian/pencarian.dart index 22e9d90..d836688 100644 --- a/lib/page/pencarian/pencarian.dart +++ b/lib/page/pencarian/pencarian.dart @@ -18,7 +18,6 @@ class PencarianState extends State { @override void initState() { super.initState(); - print("aku"); } @override diff --git a/test/mock_test.dart b/test/mock_test.dart index 4869c6e..b581146 100644 --- a/test/mock_test.dart +++ b/test/mock_test.dart @@ -1,44 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:mockito/mockito.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/bloc/LokasiResponseBloc.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; -import 'package:mockito/mockito.dart'; +import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; + +class MockNavigatorObserver extends Mock implements NavigatorObserver {} -// Create new instances of this class in each test. class MockNetwork extends Mock implements NetworkInterface {} -main() { - group('get', () { - test('returns a post if the http call completes successfully', () async { - NetworkInterface network = MockNetwork(); - - // Use Mockito to return a successful response when it calls the - // provided http.Client. - when(network.get( - url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960')) - .thenAnswer((_) async => Future>.value( - [ - { - "nama": "Coolidge", - "latitude": -23.7169139, - "longitude": -46.8498038, - "alamat": "74809 Hooker Drive", - "telepon": "+55 956 836 5799" - } - ], - )); - - //expect(await network.get(network), new TypeMatcher()); +void main() { + group('Dashboard navigation tests', () { + NavigatorObserver mockObserver; + NetworkInterface mockNetwork; + setUp(() { + //final lokasiBloc = LokasiResponseBloc(); + mockObserver = MockNavigatorObserver(); + mockNetwork = MockNetwork(); + when(mockNetwork.get(isLogin: false, url: anyNamed('url'))).thenAnswer((_) async { + await Future.delayed(Duration(milliseconds: 50)); + return Future.value( + [ + { + "nama": "Coolidge", + "latitude": -23.7169139, + "longitude": -46.8498038, + "alamat": "74809 Hooker Drive", + "telepon": "+55 956 836 5799" + } + ] + ); + }); }); - test('throws an exception if the http call completes with an error', () { - NetworkInterface network = MockNetwork(); + Future _buildDashboardPage(WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: Dashboard(), - // Use Mockito to return an unsuccessful response when it calls the - // provided http.Client. - when(network.get( - url: 'https://my.api.mockaroo.com/mall.json?key=dbcde960')) - .thenThrow(Exception); + /// This mocked observer will now receive all navigation events + /// that happen in our app. + navigatorObservers: [mockObserver], + )); - //expect( network.get(network), throwsException); - }); + /// The tester.pumpWidget() call above just built our app widget + /// and triggered the pushObserver method on the mockObserver once. + verify(mockObserver.didPush(any, any)); + } + + Future _navigateToPencarianPage(WidgetTester tester) async { + final textFieldKey = Key("Text Field Mau Kemana"); + await tester.tap(find.byKey(textFieldKey)); + await tester.pump(); + } + + testWidgets( + 'when tapping text form field, should navigate to pencarian page', + (WidgetTester tester) async { + final textFieldKeyPencarian = Key("Text Field Mau Kemana"); + await _buildDashboardPage(tester); + await _navigateToPencarianPage(tester); + verify(mockObserver.didPush(any, any)); + expect(find.byKey(textFieldKeyPencarian), findsOneWidget); + }); + + testWidgets('tapping the back button should navigate back to the dashboard', + (WidgetTester tester) async { + final backIconKey = Key("Back Icon Key"); + await _buildDashboardPage(tester); + await _navigateToPencarianPage(tester); + await tester.pump(); + final Route pushedRoute = + verify(mockObserver.didPush(captureAny, any)).captured.single; + String popResult; + pushedRoute.popped.then((result) => popResult = result); + await tester.tap(find.byKey(backIconKey)); + await tester.pumpAndSettle(); + expect(popResult, 'Take me back'); + }); }); } diff --git a/test/widget_test.dart b/test/widget_test.dart index 64ff19c..0337d30 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -14,7 +14,7 @@ void main() { await tester.pumpWidget(MaterialApp(home: Dashboard())); // Search for the childWidget in the tree and verify it exists. expect(find.byType(Scaffold), findsOneWidget); - expect(find.byType(Stack), findsNWidgets(3)); + expect(find.byType(Stack), findsNWidgets(2)); expect(find.byType(TextFormField), findsOneWidget); expect(find.byType(Icon), findsNWidgets(3)); expect(find.text('Kamu mau kemana?'), findsOneWidget); -- GitLab From 23b1867f10038f5eda2023e66ee7ff4f8fe9bb14 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Tue, 24 Mar 2020 21:53:06 +0700 Subject: [PATCH 09/14] [CHORE] add todo for testing --- lib/network/network_interface.dart | 4 ---- lib/page/pencarian/pencarian.dart | 7 ++++--- test/mock_test.dart | 3 --- test/pencarian_test.dart | 26 ++++++++++++++++++++++++++ 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lib/network/network_interface.dart b/lib/network/network_interface.dart index a3aee0f..a451cf3 100644 --- a/lib/network/network_interface.dart +++ b/lib/network/network_interface.dart @@ -1,12 +1,8 @@ import 'dart:convert'; -import 'package:ppl_disabilitas/config/strings.dart'; import 'package:ppl_disabilitas/network/CustomException.dart'; -import 'package:ppl_disabilitas/network/data/network_model.dart'; import 'package:http/http.dart' as http; import 'dart:io'; -import 'cookies_interface.dart'; - class NetworkInterface { //String key = KEY; diff --git a/lib/page/pencarian/pencarian.dart b/lib/page/pencarian/pencarian.dart index d836688..559ea3c 100644 --- a/lib/page/pencarian/pencarian.dart +++ b/lib/page/pencarian/pencarian.dart @@ -85,7 +85,7 @@ class PencarianState extends State { displayWidget = Center( child: Text("Anda belum pernah melakukan pencarian")); } else { - displayWidget = makeLokasiWidget(recentSearch); + displayWidget = makeLokasiWidget("history",recentSearch); } return Expanded( child: Column( @@ -131,7 +131,7 @@ class PencarianState extends State { case Status.COMPLETED: lokasiFromApi = snapshot.data.data; return Expanded( - flex: 2, child: makeLokasiWidget(lokasiFromApi)); + flex: 2, child: makeLokasiWidget("api",lokasiFromApi)); break; case Status.ERROR: return Center( @@ -148,12 +148,13 @@ class PencarianState extends State { ); } - Widget makeLokasiWidget(LokasiListResponse places) { + Widget makeLokasiWidget(String key, LokasiListResponse places) { return ListView.builder( shrinkWrap: true, itemCount: places.listLokasi.length, itemBuilder: (context, index) { return InkWell( + key: Key("$key-${places.listLokasi[index].nama}"), onTap: () { _bloc.saveRecentSearch(places.listLokasi[index]); }, diff --git a/test/mock_test.dart b/test/mock_test.dart index b581146..ac6dc22 100644 --- a/test/mock_test.dart +++ b/test/mock_test.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:http/http.dart'; import 'package:mockito/mockito.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:ppl_disabilitas/bloc/LokasiResponseBloc.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; @@ -15,7 +13,6 @@ void main() { NavigatorObserver mockObserver; NetworkInterface mockNetwork; setUp(() { - //final lokasiBloc = LokasiResponseBloc(); mockObserver = MockNavigatorObserver(); mockNetwork = MockNetwork(); when(mockNetwork.get(isLogin: false, url: anyNamed('url'))).thenAnswer((_) async { diff --git a/test/pencarian_test.dart b/test/pencarian_test.dart index 8b12253..1d4f32f 100644 --- a/test/pencarian_test.dart +++ b/test/pencarian_test.dart @@ -6,15 +6,41 @@ // tree, read text, and verify that the values of widget properties are correct. +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:ppl_disabilitas/page/pencarian/pencarian.dart'; +import 'package:ppl_disabilitas/network/network_interface.dart'; +class MockNetwork extends Mock implements NetworkInterface {} void main() { + MockNetwork mockNetwork; + setUp(() { + mockNetwork = MockNetwork(); + when(mockNetwork.get(isLogin: false, url: anyNamed('url'))).thenAnswer((_) async { + await Future.delayed(Duration(milliseconds: 50)); + return Future.value( + [ + { + "nama": "Coolidge", + "latitude": -23.7169139, + "longitude": -46.8498038, + "alamat": "74809 Hooker Drive", + "telepon": "+55 956 836 5799" + } + ] + ); + }); + }); testWidgets('display list view in pencarian', (WidgetTester tester) async { // Provide the childWidget to the Container. await tester.pumpWidget(MaterialApp(home: Pencarian())); + // [TODO] pencet textfieldnya, isi textfieldnya pake Coolidge + // [TODO] expect nya keluar satu item namanya coolidge, expectnya pake key aja + // [TODO] tiap item itu punya key unik // Search for the childWidget in the tree and verify it exists. //expect(find.byType(ListView), findsNWidgets); //expect(find.byType(Container), findsWidgets); -- GitLab From 32fa51e10ecd877eede551e3f2abcfda3790f148 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Tue, 24 Mar 2020 22:02:19 +0700 Subject: [PATCH 10/14] [CHORE] Update readme - add section for building models - add section for BLoC --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 67bdfef..6c0f425 100644 --- a/README.md +++ b/README.md @@ -50,4 +50,17 @@ MAPS_API_KEY=Bu*************** Run the app using the development flavor ```bash flutter run -t lib/main_dev.dart -``` \ No newline at end of file +``` +## Building Models with JsonSerializable +Jadi abis get dari API, jsonnya di map ke models biar rapih. +1. Tulis ada field apa aja dari jsonnya (bisa liat contoh yang di models/lokasi.dart) +2. bagian 'part of {nama models}.g.dart' itu harus ditulis di model yg mau dibuat. di awal emang merah, tapi biarin aja +3. kalo semua field udah di tulis, run +```bash +flutter pub run build_runner build +``` +4. nanti akan ke build file {nama models}.g.dart, yang di nomor 2 merah harusnya udah gak merah lagi + +## Passing Data with BLoC +Udah ada contohnya di /bloc (implementasi di screen nya ada di page/pencarian/pencarian.dart) +Bisa baca [disini]https://itnext.io/flutter-handling-your-network-api-calls-like-a-boss-936eef296547 sebagai panduannya \ No newline at end of file -- GitLab From 6b1a849548c930aeb1c709ac2ed19edc3a9cce95 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Wed, 25 Mar 2020 16:05:05 +0700 Subject: [PATCH 11/14] [CHORE] Add .flutter-plugins-dependencies to gitignore --- .flutter-plugins-dependencies | 2 +- .gitignore | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 88cd9c8..13e5510 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-24 21:05:48.757886","version":"1.15.17"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 16:01:43.498294","version":"1.15.17"} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 93baea4..a1b47e5 100644 --- a/.gitignore +++ b/.gitignore @@ -289,3 +289,5 @@ modules.xml # End of https://www.gitignore.io/api/linux,django,python,pycharm+all tests.output + +.flutter-plugins-dependencies -- GitLab From c8380a3bcdcaf8034d04e458676a1a31452d1391 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Wed, 25 Mar 2020 16:54:17 +0700 Subject: [PATCH 12/14] [CHORE] Debug flutter test in pipeline --- .flutter-plugins-dependencies | 10 +---- .gitlab-ci.yml | 2 +- lib/network/cookies_interface.dart | 10 ++--- lib/page/dashboard/dashboard.dart | 2 +- lib/page/pencarian/pencarian.dart | 2 +- test/mock_test.dart | 72 +++++++++++++++++------------- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index c79b89e..7b7401d 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1,9 +1 @@ -<<<<<<< HEAD -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 16:01:43.498294","version":"1.15.17"} -======= -<<<<<<< HEAD -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}]} -======= -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]}],"date_created":"2020-03-25 16:26:56.154526","version":"1.15.17"} ->>>>>>> staging ->>>>>>> PBI-2-pencarian_lokasi +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 16:48:42.556715","version":"1.15.17"} \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c73806b..da9a47c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,8 +22,8 @@ Lint: Test: stage: test script: - - flutter test --machine > tests.output - flutter test --coverage + - flutter test --machine > tests.output - lcov --summary coverage/lcov.info - genhtml coverage/lcov.info --output=coverage artifacts: diff --git a/lib/network/cookies_interface.dart b/lib/network/cookies_interface.dart index 92bebf7..6a6a079 100644 --- a/lib/network/cookies_interface.dart +++ b/lib/network/cookies_interface.dart @@ -29,7 +29,7 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File cookieFile = new File("${dir.path}/usercookies.json"); + File cookieFile = File("${dir.path}/usercookies.json"); cookieFile.createSync(); setCookie = responseHeaders["set-cookie"]; @@ -47,7 +47,7 @@ class CookiesInterface { return cookieFile; } on Exception catch (e) { print(e.toString()); - throw e; + rethrow; } } @@ -60,7 +60,7 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File cookieFile = new File(dir.path + "/searchhistory.json"); + File cookieFile = File(dir.path + "/searchhistory.json"); cookieFile.createSync(); await checkCookieFileAvailability(fileName: "searchhistory").then((available) async { if (available) { @@ -77,12 +77,12 @@ class CookiesInterface { } else { currentSearchHistory = []; } - cookieFile.writeAsString(json.encode(currentSearchHistory)); + await cookieFile.writeAsString(json.encode(currentSearchHistory)); }); return cookieFile; } on Exception catch (e) { print(e.toString()); - throw e; + rethrow; } } diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index 82f3ba6..228f490 100644 --- a/lib/page/dashboard/dashboard.dart +++ b/lib/page/dashboard/dashboard.dart @@ -46,7 +46,7 @@ class DashboardState extends State { } void enableLocationService() async { - location.changeSettings(accuracy: LocationAccuracy.HIGH); + await location.changeSettings(accuracy: LocationAccuracy.HIGH); _serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) { _serviceEnabled = await location.requestService(); diff --git a/lib/page/pencarian/pencarian.dart b/lib/page/pencarian/pencarian.dart index 559ea3c..20aad67 100644 --- a/lib/page/pencarian/pencarian.dart +++ b/lib/page/pencarian/pencarian.dart @@ -81,7 +81,7 @@ class PencarianState extends State { case Status.COMPLETED: recentSearch = snapshot.data.data; Widget displayWidget; - if (recentSearch.listLokasi.length == 0) { + if (recentSearch.listLokasi.isEmpty) { displayWidget = Center( child: Text("Anda belum pernah melakukan pencarian")); } else { diff --git a/test/mock_test.dart b/test/mock_test.dart index ac6dc22..537257f 100644 --- a/test/mock_test.dart +++ b/test/mock_test.dart @@ -3,31 +3,38 @@ import 'package:mockito/mockito.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; +import 'package:http/http.dart' as http; +import 'package:pedantic/pedantic.dart'; class MockNavigatorObserver extends Mock implements NavigatorObserver {} class MockNetwork extends Mock implements NetworkInterface {} +class MockHttp extends Mock implements http.Client {} + void main() { group('Dashboard navigation tests', () { NavigatorObserver mockObserver; NetworkInterface mockNetwork; + MockHttp mockHttp; setUp(() { mockObserver = MockNavigatorObserver(); mockNetwork = MockNetwork(); - when(mockNetwork.get(isLogin: false, url: anyNamed('url'))).thenAnswer((_) async { + mockHttp = MockHttp(); + when(mockHttp.get('http://wwww.google.com')) + .thenAnswer((_) async => http.Response('{"title": "Test"}', 200)); + when(mockNetwork.get(isLogin: false, url: anyNamed('url'))) + .thenAnswer((_) async { await Future.delayed(Duration(milliseconds: 50)); - return Future.value( - [ - { - "nama": "Coolidge", - "latitude": -23.7169139, - "longitude": -46.8498038, - "alamat": "74809 Hooker Drive", - "telepon": "+55 956 836 5799" - } - ] - ); + return Future.value([ + { + "nama": "Coolidge", + "latitude": -23.7169139, + "longitude": -46.8498038, + "alamat": "74809 Hooker Drive", + "telepon": "+55 956 836 5799" + } + ]); }); }); @@ -53,27 +60,28 @@ void main() { testWidgets( 'when tapping text form field, should navigate to pencarian page', - (WidgetTester tester) async { - final textFieldKeyPencarian = Key("Text Field Mau Kemana"); - await _buildDashboardPage(tester); - await _navigateToPencarianPage(tester); - verify(mockObserver.didPush(any, any)); - expect(find.byKey(textFieldKeyPencarian), findsOneWidget); - }); + (WidgetTester tester) async { + final textFieldKeyPencarian = Key("Text Field Mau Kemana"); + await _buildDashboardPage(tester); + await _navigateToPencarianPage(tester); + + verify(mockObserver.didPush(any, any)); + expect(find.byKey(textFieldKeyPencarian), findsOneWidget); + }); testWidgets('tapping the back button should navigate back to the dashboard', - (WidgetTester tester) async { - final backIconKey = Key("Back Icon Key"); - await _buildDashboardPage(tester); - await _navigateToPencarianPage(tester); - await tester.pump(); - final Route pushedRoute = - verify(mockObserver.didPush(captureAny, any)).captured.single; - String popResult; - pushedRoute.popped.then((result) => popResult = result); - await tester.tap(find.byKey(backIconKey)); - await tester.pumpAndSettle(); - expect(popResult, 'Take me back'); - }); + (WidgetTester tester) async { + final backIconKey = Key("Back Icon Key"); + await _buildDashboardPage(tester); + await _navigateToPencarianPage(tester); + await tester.pump(); + final Route pushedRoute = + verify(mockObserver.didPush(captureAny, any)).captured.single; + String popResult; + unawaited(pushedRoute.popped.then((result) => popResult = result)); + await tester.tap(find.byKey(backIconKey)); + await tester.pumpAndSettle(); + expect(popResult, 'Take me back'); + }); }); } -- GitLab From eaf9e8be70216c0f6040a99bd28658abbb700280 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Wed, 25 Mar 2020 16:58:32 +0700 Subject: [PATCH 13/14] [REFACTOR] Change variable name --- .flutter-plugins-dependencies | 2 +- lib/repository/LokasiRepository.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 7b7401d..98f0adf 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 16:48:42.556715","version":"1.15.17"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 16:56:46.023331","version":"1.15.17"} \ No newline at end of file diff --git a/lib/repository/LokasiRepository.dart b/lib/repository/LokasiRepository.dart index 6eb3f90..c838e73 100644 --- a/lib/repository/LokasiRepository.dart +++ b/lib/repository/LokasiRepository.dart @@ -16,8 +16,8 @@ class LokasiRepository { Future fetchRecentSearch() async { var response; - await CookiesInterface().checkCookieFileAvailability(fileName: "searchhistory").then((bool) async { - if (!bool) { + await CookiesInterface().checkCookieFileAvailability(fileName: "searchhistory").then((boolean) async { + if (!boolean) { response = []; } else { await CookiesInterface().getCookieFile(fileName: "searchhistory").then((cookie) { -- GitLab From 1e7a7f820dbdd7ec0dcd0f30a7e2ac65565a90b2 Mon Sep 17 00:00:00 2001 From: Fakhira Date: Wed, 25 Mar 2020 17:24:26 +0700 Subject: [PATCH 14/14] [REFACTOR] Expect stack with key --- .flutter-plugins-dependencies | 2 +- lib/page/dashboard/dashboard.dart | 2 +- test/widget_test.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 98f0adf..0132667 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 16:56:46.023331","version":"1.15.17"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":[]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-1.0.6\\\\","dependencies":[]},{"name":"google_maps_flutter","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_maps_flutter-0.5.24+1\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location-2.5.3\\\\","dependencies":[]},{"name":"path_provider","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.5\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"D:\\\\Flutter\\\\flutter_windows_v1.9.1+hotfix.2-stable\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}],"date_created":"2020-03-25 17:23:41.601639","version":"1.15.17"} \ No newline at end of file diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index 228f490..a8c24ec 100644 --- a/lib/page/dashboard/dashboard.dart +++ b/lib/page/dashboard/dashboard.dart @@ -73,7 +73,7 @@ class DashboardState extends State { Widget build(BuildContext context) { return Scaffold( drawer: BisaGoDrawer(), - body: Stack(children: [ + body: Stack(key: Key("Stack"),children: [ _buildGoogleMap(context), InkWell( key: Key("Navigate to Pencarian"), diff --git a/test/widget_test.dart b/test/widget_test.dart index 0337d30..0a22397 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -14,7 +14,7 @@ void main() { await tester.pumpWidget(MaterialApp(home: Dashboard())); // Search for the childWidget in the tree and verify it exists. expect(find.byType(Scaffold), findsOneWidget); - expect(find.byType(Stack), findsNWidgets(2)); + expect(find.byKey(Key("Stack")), findsOneWidget); expect(find.byType(TextFormField), findsOneWidget); expect(find.byType(Icon), findsNWidgets(3)); expect(find.text('Kamu mau kemana?'), findsOneWidget); -- GitLab