├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── app ├── .gitignore ├── build.gradle └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ ├── com │ │ │ └── mycompany │ │ │ │ └── flightstatuslistview │ │ │ │ ├── ArrayEmptyException.java │ │ │ │ ├── FlightModel.java │ │ │ │ ├── FlightViewModel.java │ │ │ │ ├── boardingScreen │ │ │ │ ├── BoardingActivity.java │ │ │ │ ├── BoardingConfigurator.java │ │ │ │ ├── BoardingInteractor.java │ │ │ │ ├── BoardingModel.java │ │ │ │ ├── BoardingPresenter.java │ │ │ │ ├── BoardingRouter.java │ │ │ │ ├── BoardingWorker.java │ │ │ │ └── CheckINModel.java │ │ │ │ ├── detailScreen │ │ │ │ └── FlightDetailActivity.java │ │ │ │ ├── homeScreen │ │ │ │ ├── FlightWorker.java │ │ │ │ ├── HomeActivity.java │ │ │ │ ├── HomeConfigurator.java │ │ │ │ ├── HomeInteractor.java │ │ │ │ ├── HomeModel.java │ │ │ │ ├── HomePresenter.java │ │ │ │ └── HomeRouter.java │ │ │ │ └── pastTripScreen │ │ │ │ └── PastTripActivity.java │ │ └── util │ │ │ └── CalendarUtil.java │ └── res │ │ ├── drawable │ │ ├── ic_plan_landing.xml │ │ ├── ic_plan_takeoff.xml │ │ ├── shape_circle_stroke.xml │ │ ├── shape_rectangle_fill_light.xml │ │ └── shape_rectangle_stroke.xml │ │ ├── layout │ │ ├── activity_flight_boarding.xml │ │ ├── activity_flight_detail.xml │ │ ├── activity_main.xml │ │ ├── activity_past_trip.xml │ │ ├── cell_flight_status.xml │ │ ├── cell_trip_list.xml │ │ └── flight_detail.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── plan_landing.svg │ │ ├── plan_takeoff.svg │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── mycompany │ └── flightstatuslistview │ └── homeScreen │ ├── HomeActivityUnitTest.java │ ├── HomeInteractorUnitTest.java │ ├── HomePresenterUnitTest.java │ └── HomeRouterUnitTest.java ├── build.gradle ├── gradle.properties └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | projectFilesBackup/ 3 | gradle/ 4 | .gradle/ 5 | .idea/** 6 | .notidea/ 7 | *.DS_Store 8 | *.iml 9 | app/build/** 10 | 11 | 12 | # built application files 13 | *.apk 14 | *.ap_ 15 | 16 | # files for the dex VM 17 | *.dex 18 | 19 | # Java class files 20 | *.class 21 | 22 | # built native files (uncomment if you build your own) 23 | # *.o 24 | # *.so 25 | 26 | # generated files 27 | bin/ 28 | gen/ 29 | 30 | # Ignore gradle files 31 | .gradle/ 32 | build/ 33 | 34 | # Local configuration file (sdk path, etc) 35 | local.properties 36 | 37 | # Proguard folder generated by Eclipse 38 | proguard/ 39 | 40 | # Eclipse Metadata 41 | .metadata/ 42 | 43 | # Mac OS X clutter 44 | *.DS_Store 45 | 46 | # Windows clutter 47 | Thumbs.db 48 | 49 | # Intellij IDEA (see https://intellij-support.jetbrains.com/entries/23393067) 50 | .idea/workspace.xml 51 | .idea/tasks.xml 52 | .idea/datasources.xml 53 | .idea/dataSources.ids 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Mohanraj K.M. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Test Driven Android Development - Clean Code Android 2 | #### Inspired from [Clean Architecture][1] from Uncle Bob, [Google Android samples][3] and [Clean Swift][2] 3 | ##### This design is chosen with a singular focus - testablity. 4 | ##### Want to learn about Android Clean Code ? follow [here][7] 5 | 6 | 7 | ## Quick Start 8 | 1. Clone and open in Android Studio 9 | 2. It should work with out any issues 10 | 11 | 12 | ## Whats Next ? 13 | Want to use it your projects - bothered about the too much boilerplate code ? You can generate them with in few seconds - check [here][5] 14 | 15 | ### Contribute 16 | Welcome to contribute, feel free to change and open a PR. 17 | 18 | ### License 19 | [MIT License][6] 20 | 21 | #### TODO 22 | 1. Create example test cases for Router 23 | 2. Create code and test examples for the detail page. 24 | 3. Create example for Fragments 25 | 26 | #### Inspiration 27 | 28 | This project ideas aren't new in any way. Credit has to be given to the following projects, listed in autobiographical order. 29 | 30 | [Clean Architecture][1] 31 | 32 | [clean-swift][2] 33 | 34 | [1]: https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html 35 | [2]: http://clean-swift.com 36 | [3]: https://github.com/googlesamples/android-testing 37 | [4]: https://riggaroo.co.za/custom-file-templates-android-studio/ 38 | [5]: https://github.com/kmmraj/androidcleancode-generator 39 | [6]: ./LICENSE 40 | [7]: https://medium.com/@kmmraj/android-clean-code-part-1-c66da6551d1 41 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion '28.0.2' 6 | 7 | defaultConfig { 8 | applicationId "com.mycompany.flightstatuslistview" 9 | minSdkVersion 15 10 | targetSdkVersion 27 11 | versionCode 1 12 | versionName "1.0" 13 | vectorDrawables.useSupportLibrary = true 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | 22 | testOptions { 23 | unitTests { 24 | includeAndroidResources = true 25 | } 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | testImplementation 'junit:junit:4.12' 32 | testImplementation 'org.robolectric:robolectric:3.8' 33 | // testImplementation 'org.robolectric:shadows-support-v4:3.0' 34 | // testImplementation 'org.mockito:mockito-core:2.18.3' 35 | implementation 'com.android.support:appcompat-v7:27.1.1' 36 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 37 | } 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/ArrayEmptyException.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview; 2 | 3 | /** 4 | * Created by mkaratadipalayam on 28/05/17. 5 | */ 6 | 7 | public class ArrayEmptyException extends RuntimeException { 8 | 9 | private String msg; 10 | 11 | public ArrayEmptyException() { 12 | msg = "ArrayEmptyException"; 13 | } 14 | 15 | public ArrayEmptyException(String exceptionMessage) { 16 | msg = exceptionMessage; 17 | } 18 | 19 | public String getMessage() { 20 | return msg; 21 | } 22 | 23 | public String toString() { 24 | return (msg); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/FlightModel.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by mkaratadipalayam on 20/09/16. 8 | */ 9 | public class FlightModel implements Parcelable { 10 | 11 | public String flightName; 12 | public String startingTime; 13 | public String departureCity; 14 | public String arrivalCity; 15 | public String departureTime; 16 | public String arrivalTime; 17 | 18 | public FlightModel() {} 19 | 20 | protected FlightModel(Parcel in) { 21 | flightName = in.readString(); 22 | startingTime = in.readString(); 23 | departureCity = in.readString(); 24 | arrivalCity = in.readString(); 25 | departureTime = in.readString(); 26 | arrivalTime = in.readString(); 27 | } 28 | 29 | public static final Creator CREATOR = new Creator() { 30 | @Override 31 | public FlightModel createFromParcel(Parcel in) { 32 | return new FlightModel(in); 33 | } 34 | 35 | @Override 36 | public FlightModel[] newArray(int size) { 37 | return new FlightModel[size]; 38 | } 39 | }; 40 | 41 | @Override 42 | public int describeContents() { 43 | return 0; 44 | } 45 | 46 | @Override 47 | public void writeToParcel(Parcel dest, int flags) { 48 | dest.writeString(flightName); 49 | dest.writeString(startingTime); 50 | dest.writeString(departureCity); 51 | dest.writeString(arrivalCity); 52 | dest.writeString(departureTime); 53 | dest.writeString(arrivalTime); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/FlightViewModel.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | /** 7 | * Created by mkaratadipalayam on 11/10/16. 8 | */ 9 | 10 | public class FlightViewModel extends FlightModel implements Parcelable { 11 | 12 | 13 | public String noOfDaysToFly; 14 | 15 | 16 | public FlightViewModel() {} 17 | 18 | protected FlightViewModel(Parcel in) { 19 | super(in); 20 | noOfDaysToFly = in.readString(); 21 | } 22 | 23 | public static final Creator CREATOR = new Creator() { 24 | @Override 25 | public FlightViewModel createFromParcel(Parcel in) { 26 | return new FlightViewModel(in); 27 | } 28 | 29 | @Override 30 | public FlightViewModel[] newArray(int size) { 31 | return new FlightViewModel[size]; 32 | } 33 | }; 34 | 35 | @Override 36 | public int describeContents() { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public void writeToParcel(Parcel dest, int flags) { 42 | super.writeToParcel(dest, flags); 43 | dest.writeString(noOfDaysToFly); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingActivity.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.widget.TextView; 7 | 8 | import com.mycompany.flightstatuslistview.FlightModel; 9 | import com.mycompany.flightstatuslistview.R; 10 | 11 | 12 | interface BoardingActivityInput { 13 | void displayBoardingData(BoardingViewModel viewModel); 14 | } 15 | 16 | 17 | public class BoardingActivity extends AppCompatActivity 18 | implements BoardingActivityInput { 19 | 20 | private static String TAG = BoardingActivity.class.getSimpleName(); 21 | BoardingInteractorInput output; 22 | BoardingRouter router; 23 | private FlightModel flightModel; 24 | private TextView mPassengerName; 25 | private TextView mFlightCode; 26 | private TextView mDepartureCity; 27 | private TextView mArrivalCity; 28 | private TextView mBoardingTime; 29 | private TextView mDepartureTime; 30 | private TextView mDepartureDate; 31 | private TextView mArrivalTime; 32 | private TextView mGate; 33 | private TextView mTerminal; 34 | private TextView mSeat; 35 | 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_flight_boarding); 40 | flightModel = getIntent().getParcelableExtra("flight"); 41 | bindViews(); 42 | //do the setup 43 | 44 | BoardingConfigurator.INSTANCE.configure(this); 45 | BoardingRequest aBoardingRequest = new BoardingRequest(); 46 | //populate the request 47 | 48 | 49 | output.fetchBoardingData(aBoardingRequest); 50 | // Do other work 51 | } 52 | 53 | private void bindViews(){ 54 | mPassengerName = (TextView) findViewById(R.id.tv_passengerName); 55 | mFlightCode = (TextView) findViewById(R.id.tv_flightNumberValue); 56 | mDepartureCity = (TextView) findViewById(R.id.tv_departureAirport); 57 | mArrivalCity = (TextView) findViewById(R.id.tv_arrivalAirport); 58 | mBoardingTime = (TextView) findViewById(R.id.tv_boardingTime); 59 | mDepartureTime = (TextView) findViewById(R.id.tv_departureTime); 60 | mArrivalTime = (TextView) findViewById(R.id.tv_arrivalTime); 61 | mDepartureDate = (TextView) findViewById(R.id.tv_departureDate); 62 | mGate = (TextView) findViewById(R.id.tv_gateValue); 63 | mTerminal = (TextView) findViewById(R.id.tv_terminalValue); 64 | mSeat = (TextView) findViewById(R.id.tv_seatValue); 65 | } 66 | 67 | 68 | @Override 69 | public void displayBoardingData(BoardingViewModel viewModel) { 70 | Log.e(TAG, "displayBoardingData() called with: viewModel = [" + viewModel + "]"); 71 | // Deal with the data 72 | CheckINModel checkINModel = viewModel.checkINModel; 73 | mPassengerName.setText("Mohan Karats"); 74 | // mFlightCode.setText(flightModel.flightName); 75 | mArrivalCity.setText(flightModel.arrivalCity); 76 | mArrivalTime.setText(flightModel.arrivalTime); 77 | mDepartureCity.setText(flightModel.departureCity); 78 | mDepartureTime.setText(flightModel.departureTime); 79 | // mBoardingTime.setText(flightModel.); 80 | mDepartureDate.setText(flightModel.startingTime); 81 | 82 | 83 | 84 | mGate.setText(checkINModel.gate); 85 | mTerminal.setText(checkINModel.terminal); 86 | mSeat.setText(checkINModel.seat); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | import java.lang.ref.WeakReference; 4 | 5 | 6 | public enum BoardingConfigurator { 7 | INSTANCE; 8 | 9 | public void configure(BoardingActivity activity) { 10 | 11 | BoardingRouter router = new BoardingRouter(); 12 | router.activity = new WeakReference<>(activity); 13 | 14 | BoardingPresenter presenter = new BoardingPresenter(); 15 | presenter.output = new WeakReference(activity); 16 | 17 | BoardingInteractor interactor = new BoardingInteractor(); 18 | interactor.output = presenter; 19 | 20 | if (activity.output == null) { 21 | activity.output = interactor; 22 | } 23 | if (activity.router == null) { 24 | activity.router = router; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingInteractor.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | interface BoardingInteractorInput { 4 | void fetchBoardingData(BoardingRequest request); 5 | } 6 | 7 | 8 | public class BoardingInteractor implements BoardingInteractorInput { 9 | 10 | public static String TAG = BoardingInteractor.class.getSimpleName(); 11 | public BoardingPresenterInput output; 12 | private BoardingWorkerInput aBoardingWorkerInput; 13 | 14 | private BoardingWorkerInput getBoardingWorkerInput() { 15 | if (aBoardingWorkerInput == null) return new BoardingWorker(); 16 | return aBoardingWorkerInput; 17 | } 18 | 19 | public void setBoardingWorkerInput(BoardingWorkerInput aBoardingWorkerInput) { 20 | this.aBoardingWorkerInput = aBoardingWorkerInput; 21 | } 22 | 23 | @Override 24 | public void fetchBoardingData(BoardingRequest request) { 25 | aBoardingWorkerInput = getBoardingWorkerInput(); 26 | BoardingResponse aBoardingResponse = new BoardingResponse(); 27 | // Call the workers 28 | aBoardingResponse.checkINModel = aBoardingWorkerInput.getCheckINDetails(request); 29 | output.presentBoardingData(aBoardingResponse); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingModel.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | public class BoardingModel { 4 | } 5 | 6 | class BoardingViewModel { 7 | //filter to have only the needed data 8 | public CheckINModel checkINModel; 9 | 10 | } 11 | 12 | class BoardingRequest { 13 | public String ffNumber; 14 | } 15 | 16 | class BoardingResponse { 17 | public CheckINModel checkINModel; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingPresenter.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | import java.lang.ref.WeakReference; 4 | 5 | interface BoardingPresenterInput { 6 | void presentBoardingData(BoardingResponse response); 7 | } 8 | 9 | 10 | public class BoardingPresenter implements BoardingPresenterInput { 11 | 12 | public static String TAG = BoardingPresenter.class.getSimpleName(); 13 | 14 | //weak var output: HomePresenterOutput! 15 | public WeakReference output; 16 | 17 | 18 | @Override 19 | public void presentBoardingData(BoardingResponse response) { 20 | // Log.e(TAG, "presentBoardingData() called with: response = [" + response + "]"); 21 | //Do your decoration or filtering here 22 | // Model and Viewmodel is same here 23 | BoardingViewModel boardingViewModel = new BoardingViewModel(); 24 | boardingViewModel.checkINModel = response.checkINModel; 25 | 26 | output.get().displayBoardingData(boardingViewModel); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingRouter.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.widget.AdapterView; 7 | 8 | import java.lang.ref.WeakReference; 9 | 10 | 11 | interface BoardingRouterInput { 12 | Intent navigateToSomeWhere(int position); 13 | 14 | void passDataToNextScene(int position, Intent intent); 15 | } 16 | 17 | public class BoardingRouter implements BoardingRouterInput, AdapterView.OnItemClickListener { 18 | 19 | public static String TAG = BoardingRouter.class.getSimpleName(); 20 | public WeakReference activity; 21 | 22 | 23 | @NonNull 24 | @Override 25 | public Intent navigateToSomeWhere(int position) { 26 | //Based on the position or someother data decide what is the next scene 27 | //Intent intent = new Intent(activity.get(),NextActivity.class); 28 | //return intent; 29 | return null; 30 | } 31 | 32 | @Override 33 | public void passDataToNextScene(int position, Intent intent) { 34 | //Based on the position or someother data decide the data for the next scene 35 | // BoardingModel flight = activity.get().listOfSomething.get(position); 36 | // intent.putExtra("flight",flight); 37 | } 38 | 39 | @Override 40 | public void onItemClick(AdapterView parent, View view, int position, long id) { 41 | // Log.e(TAG, "onItemClick() called with: parent = [" + parent + "], view = [" + view + "], position = [" + position + "], id = [" + id + "]"); 42 | Intent intent = navigateToSomeWhere(position); 43 | passDataToNextScene(position, intent); 44 | activity.get().startActivity(intent); 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/BoardingWorker.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | interface BoardingWorkerInput { 4 | //Define needed interfaces 5 | CheckINModel getCheckINDetails(BoardingRequest boardingRequest); 6 | } 7 | 8 | public class BoardingWorker implements BoardingWorkerInput { 9 | 10 | @Override 11 | public CheckINModel getCheckINDetails(BoardingRequest boardingRequest) { 12 | CheckINModel checkINModel = new CheckINModel(); 13 | checkINModel.flightName = ""; 14 | checkINModel.startingTime = ""; 15 | checkINModel.gate="24"; 16 | checkINModel.terminal="2"; 17 | checkINModel.seat="6A"; 18 | return checkINModel; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/boardingScreen/CheckINModel.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.boardingScreen; 2 | 3 | /** 4 | * Created by mkaratadipalayam on 19/06/17. 5 | */ 6 | 7 | class CheckINModel { 8 | public String flightName; 9 | public String startingTime; 10 | public String terminal; 11 | public String gate; 12 | public String seat; 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/detailScreen/FlightDetailActivity.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.detailScreen; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.widget.TextView; 7 | 8 | import com.mycompany.flightstatuslistview.FlightModel; 9 | import com.mycompany.flightstatuslistview.R; 10 | 11 | import java.util.Calendar; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | public class FlightDetailActivity extends AppCompatActivity { 15 | 16 | private FlightModel flightModel; 17 | private static final String TAG = FlightDetailActivity.class.getSimpleName(); 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_flight_detail); 23 | getSupportActionBar().hide(); 24 | flightModel = getIntent().getParcelableExtra("flight"); 25 | 26 | if(flightModel != null){ 27 | TextView flightNameTextView = (TextView) findViewById(R.id.flightName); 28 | flightNameTextView.setText("Flight: "+flightModel.flightName); 29 | TextView startingTimeTextView = (TextView) findViewById(R.id.startingTime); 30 | startingTimeTextView.setText("Date: "+flightModel.startingTime); 31 | 32 | 33 | 34 | TextView checkInStatus = (TextView) findViewById(R.id.checkInStatus); 35 | 36 | 37 | String flightTime = flightModel.startingTime; 38 | 39 | int year = Integer.parseInt(flightTime.substring(0,4)); 40 | int month = Integer.parseInt(flightTime.substring(5,7)); 41 | int day = Integer.parseInt(flightTime.substring(8,10)); 42 | 43 | //Log.e(TAG,"year/month/day is "+ year+ "/"+month+"/"+day); 44 | 45 | Calendar startingTime = Calendar.getInstance(); 46 | startingTime.set(year,month-1,day,0,0,0); 47 | //Calendar currentTime = Calendar.getInstance(); 48 | //Log.e(TAG,"Current Time is : "+ currentTime.getTime()); 49 | 50 | long msDiff = startingTime.getTimeInMillis() - Calendar.getInstance().getTimeInMillis(); 51 | long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff); 52 | Log.e(TAG,"diff is "+ daysDiff); 53 | 54 | 55 | if (daysDiff <= 30){ 56 | checkInStatus.setBackgroundColor(getResources().getColor(android.R.color.holo_green_light)); 57 | checkInStatus.setText("Checkin open"); 58 | } else if (daysDiff <= 60){ 59 | checkInStatus.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_light)); 60 | checkInStatus.setText("Checkin not Open"); 61 | } else { 62 | checkInStatus.setBackgroundColor(getResources().getColor(android.R.color.holo_purple)); 63 | checkInStatus.setText("Checkin not open - Come back"); 64 | } 65 | 66 | 67 | 68 | 69 | // TextView arrivalCity = (TextView) findViewById(R.id.arrivalCity); 70 | // arrivalCity.setText("Gate: "+flightModel.arrivalCity); 71 | // TextView departureTime = (TextView) findViewById(R.id.departureTime); 72 | // departureTime.setText("Terminal: "+flightModel.departureTime); 73 | 74 | 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/FlightWorker.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import com.mycompany.flightstatuslistview.FlightModel; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by mkaratadipalayam on 20/09/16. 9 | */ 10 | 11 | interface FlightWorkerInput{ 12 | ArrayList getFutureFlights(); 13 | ArrayList getPastFlights(); 14 | } 15 | public class FlightWorker implements FlightWorkerInput { 16 | 17 | public ArrayList getFutureFlights() { 18 | 19 | ArrayList flightsList = new ArrayList<>(); 20 | 21 | FlightModel flight1 = new FlightModel(); 22 | flight1.flightName = "9Z 231"; 23 | flight1.startingTime = "2017/10/31"; 24 | flight1.departureCity = "BLR"; 25 | flight1.arrivalCity = "CJB"; 26 | flight1.departureTime = "06:00"; 27 | flight1.arrivalTime = "06:50"; 28 | 29 | flightsList.add(flight1); 30 | 31 | FlightModel flight2 = new FlightModel(); 32 | flight2.flightName = "9Z 15"; 33 | flight2.startingTime = "2017/02/31"; 34 | flight2.departureCity = "BLR"; 35 | flight2.arrivalCity = "CJB"; 36 | flight2.departureTime = "09:00"; 37 | flight2.arrivalTime = "09:50"; 38 | flightsList.add(flight2); 39 | 40 | FlightModel flight3 = new FlightModel(); 41 | flight3.flightName = "9Z 142"; 42 | flight3.startingTime = "2017/12/31"; 43 | flight3.departureCity = "BLR"; 44 | flight3.arrivalCity = "CJB"; 45 | flight3.departureTime = "18:10"; 46 | flight3.arrivalTime = "19:00"; 47 | flightsList.add(flight3); 48 | 49 | return flightsList; 50 | } 51 | 52 | public ArrayList getPastFlights() { 53 | 54 | ArrayList flightsList = new ArrayList<>(); 55 | 56 | FlightModel flight1 = new FlightModel(); 57 | flight1.flightName = "9Z 231"; 58 | flight1.startingTime = "2015/10/31"; 59 | flight1.departureCity = "BLR"; 60 | flight1.arrivalCity = "CJB"; 61 | flight1.departureTime = "06:00"; 62 | flight1.arrivalTime = "06:50"; 63 | 64 | flightsList.add(flight1); 65 | 66 | FlightModel flight2 = new FlightModel(); 67 | flight2.flightName = "9Z 15"; 68 | flight2.startingTime = "2015/11/31"; 69 | flight2.departureCity = "BLR"; 70 | flight2.arrivalCity = "CJB"; 71 | flight2.departureTime = "09:00"; 72 | flight2.arrivalTime = "09:50"; 73 | flightsList.add(flight2); 74 | 75 | FlightModel flight3 = new FlightModel(); 76 | flight3.flightName = "9Z 142"; 77 | flight3.startingTime = "2015/12/31"; 78 | flight3.departureCity = "BLR"; 79 | flight3.arrivalCity = "CJB"; 80 | flight3.departureTime = "18:10"; 81 | flight3.arrivalTime = "19:00"; 82 | flightsList.add(flight3); 83 | 84 | return flightsList; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/HomeActivity.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.BaseAdapter; 10 | import android.widget.ListView; 11 | import android.widget.TextView; 12 | 13 | import com.mycompany.flightstatuslistview.FlightViewModel; 14 | import com.mycompany.flightstatuslistview.R; 15 | 16 | import java.util.ArrayList; 17 | 18 | 19 | 20 | interface HomeActivityInput { 21 | void displayHomeMetaData(HomeViewModel viewModel); 22 | } 23 | 24 | //interface HomeRouterOutput { 25 | // ArrayList listOfVMFlights = null; 26 | // HomeRouter router = null; 27 | //} 28 | 29 | 30 | 31 | public class HomeActivity extends AppCompatActivity implements HomeActivityInput { 32 | 33 | public ArrayList listOfVMFlights; 34 | 35 | HomeInteractorInput output; 36 | HomeRouter router; 37 | 38 | public static String TAG = HomeActivity.class.getSimpleName(); 39 | 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | setContentView(R.layout.activity_main); 45 | getSupportActionBar().hide(); 46 | 47 | HomeConfigurator.INSTANCE.configure(this); 48 | fetchMetaData(); 49 | createFlightListView(); 50 | } 51 | 52 | public void fetchMetaData() { 53 | // create Request and set the needed input 54 | HomeRequest homeRequest = new HomeRequest(); 55 | homeRequest.isFutureTrips = true; 56 | // Call the output to fetch the data 57 | output.fetchHomeMetaData(homeRequest); 58 | } 59 | 60 | private void createFlightListView() { 61 | ListView listView = (ListView) findViewById(R.id.listOfFlights); 62 | listView.setAdapter(new FlightListAdapter()); 63 | listView.setClickable(true); 64 | listView.setOnItemClickListener(router); 65 | } 66 | 67 | @Override 68 | public void displayHomeMetaData(HomeViewModel viewModel) { 69 | Log.e(TAG, "displayHomeMetaData() called with: viewModel = [" + viewModel + "]"); 70 | listOfVMFlights = viewModel.listOfFlights; 71 | } 72 | 73 | 74 | 75 | 76 | 77 | private class FlightListAdapter extends BaseAdapter { 78 | 79 | private LayoutInflater layoutInflater; 80 | 81 | FlightListAdapter(){ 82 | layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 83 | } 84 | @Override 85 | public int getCount() { 86 | return listOfVMFlights.size(); 87 | } 88 | 89 | @Override 90 | public Object getItem(int position) { 91 | return listOfVMFlights.get(position); 92 | } 93 | 94 | @Override 95 | public long getItemId(int position) { 96 | return position; 97 | } 98 | 99 | @Override 100 | public View getView(int position, View convertView, ViewGroup parent) { 101 | 102 | if(convertView == null){ 103 | convertView = layoutInflater.inflate(R.layout.cell_trip_list,null); 104 | ViewHolder viewHolder = new ViewHolder(); 105 | viewHolder.flightNameTextView = (TextView) convertView.findViewById(R.id.tv_flightNumberValue); 106 | viewHolder.startTimeTextView = (TextView) convertView.findViewById(R.id.tv_flightTimeDescription); 107 | convertView.setTag(viewHolder); 108 | } 109 | ViewHolder viewHolder = (ViewHolder) convertView.getTag(); 110 | viewHolder.flightNameTextView.setText( listOfVMFlights.get(position).flightName); 111 | viewHolder.startTimeTextView.setText( listOfVMFlights.get(position).noOfDaysToFly); 112 | return convertView; 113 | } 114 | } 115 | 116 | class ViewHolder { 117 | TextView flightNameTextView; 118 | TextView startTimeTextView; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/HomeConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import java.lang.ref.WeakReference; 4 | 5 | /** 6 | * Created by mkaratadipalayam on 10/10/16. 7 | */ 8 | 9 | public enum HomeConfigurator { 10 | INSTANCE; 11 | public void configure(HomeActivity activity){ 12 | 13 | HomeRouter router = new HomeRouter(); 14 | router.activity = new WeakReference<>(activity); 15 | 16 | HomePresenter presenter = new HomePresenter(); 17 | presenter.output = new WeakReference(activity); 18 | 19 | HomeInteractor interactor = new HomeInteractor(); 20 | interactor.output = presenter; 21 | 22 | if (activity.output == null){ 23 | activity.output = interactor; 24 | } 25 | if (activity.router == null){ 26 | activity.router = router; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/HomeInteractor.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import android.util.Log; 4 | 5 | import com.mycompany.flightstatuslistview.ArrayEmptyException; 6 | 7 | /** 8 | * Created by mkaratadipalayam on 10/10/16. 9 | */ 10 | 11 | interface HomeInteractorInput { 12 | void fetchHomeMetaData(HomeRequest request); 13 | } 14 | 15 | public class HomeInteractor implements HomeInteractorInput{ 16 | 17 | public HomePresenterInput output; 18 | 19 | public FlightWorkerInput flightWorkerInput; 20 | 21 | 22 | public FlightWorkerInput getFlightWorkerInput() { 23 | if (flightWorkerInput == null) return new FlightWorker(); 24 | return flightWorkerInput; 25 | } 26 | 27 | public void setFlightWorkerInput(FlightWorkerInput flightWorkerInput) { 28 | this.flightWorkerInput = flightWorkerInput; 29 | } 30 | 31 | public static String TAG = HomeInteractor.class.getSimpleName(); 32 | 33 | @Override 34 | public void fetchHomeMetaData(HomeRequest request) { 35 | Log.e(TAG,"In method fetchHomeMetaData"); 36 | flightWorkerInput = getFlightWorkerInput(); 37 | HomeResponse homeResponse = new HomeResponse(); 38 | if(request.isFutureTrips) { 39 | homeResponse.listOfFlights = flightWorkerInput.getFutureFlights(); 40 | } else { 41 | homeResponse.listOfFlights = flightWorkerInput.getPastFlights(); 42 | } 43 | //TODO : Add failure case here 44 | if(null == homeResponse.listOfFlights || homeResponse.listOfFlights.isEmpty()) { 45 | throw new ArrayEmptyException("Empty Flight List"); 46 | } 47 | 48 | output.presentHomeMetaData(homeResponse); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/HomeModel.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import com.mycompany.flightstatuslistview.FlightModel; 4 | import com.mycompany.flightstatuslistview.FlightViewModel; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Created by mkaratadipalayam on 10/10/16. 10 | */ 11 | 12 | public class HomeModel { 13 | } 14 | class HomeViewModel{ 15 | //TODO - filter to have only the needed data 16 | ArrayList listOfFlights; 17 | } 18 | class HomeRequest{ 19 | boolean isFutureTrips; 20 | } 21 | 22 | class HomeResponse { 23 | ArrayList listOfFlights; 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/HomePresenter.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.util.Log; 5 | 6 | import com.mycompany.flightstatuslistview.FlightModel; 7 | import com.mycompany.flightstatuslistview.FlightViewModel; 8 | 9 | import java.lang.ref.WeakReference; 10 | import java.util.ArrayList; 11 | import java.util.Calendar; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | interface HomePresenterInput { 15 | void presentHomeMetaData(HomeResponse response); 16 | } 17 | 18 | public class HomePresenter implements HomePresenterInput { 19 | 20 | public static String TAG = HomePresenter.class.getSimpleName(); 21 | 22 | public WeakReference output; 23 | private Calendar currentTime; 24 | 25 | 26 | public Calendar getCurrentTime() { 27 | if(currentTime == null) return Calendar.getInstance(); 28 | return currentTime; 29 | } 30 | 31 | 32 | 33 | public void setCurrentTime(Calendar currentTime) { 34 | this.currentTime = currentTime; 35 | } 36 | 37 | @Override 38 | public void presentHomeMetaData(HomeResponse response) { 39 | // Log.e(TAG, "presentHomeMetaData() called with: response = [" + response + "]"); 40 | //Do your decoration or filtering here 41 | HomeViewModel homeViewModel = new HomeViewModel(); 42 | homeViewModel.listOfFlights = new ArrayList<>(); 43 | 44 | 45 | if (response.listOfFlights != null) { 46 | 47 | for (FlightModel fm : response.listOfFlights) { 48 | FlightViewModel fvm = new FlightViewModel(); 49 | 50 | fvm.departureCity = fm.departureCity; 51 | fvm.arrivalCity = fm.arrivalCity; 52 | fvm.flightName = fm.flightName; 53 | fvm.startingTime = fm.startingTime; 54 | fvm.departureTime = fm.departureTime; 55 | fvm.arrivalTime = fm.arrivalTime; 56 | //Decoration 57 | Calendar startingTime = getCalendar(fvm.startingTime); 58 | long daysDiff = getDaysDiff(getCurrentTime().getTimeInMillis(),startingTime.getTimeInMillis()); 59 | setDaysFlyDecorationText(fvm, daysDiff,getCurrentTime().getTimeInMillis(),startingTime.getTimeInMillis()); 60 | 61 | homeViewModel.listOfFlights.add(fvm); 62 | } 63 | 64 | 65 | output.get().displayHomeMetaData(homeViewModel); 66 | } 67 | } 68 | 69 | private void setDaysFlyDecorationText(FlightViewModel fvm, long daysDiff,long startTime,long endTime) { 70 | if(endTime > startTime){ 71 | fvm.noOfDaysToFly = "You have " + daysDiff + " days to fly"; 72 | } else { 73 | //daysDiff =-daysDiff; 74 | fvm.noOfDaysToFly = "It has been " + daysDiff + " days since you flew"; 75 | } 76 | } 77 | 78 | @NonNull 79 | private Calendar getCalendar(String date) { 80 | //Date should be in the format YYYY/MM/DD if not return 81 | if (date != null && !date.isEmpty() && date.length() == 10 ) { 82 | int year = Integer.parseInt(date.substring(0, 4)); 83 | int month = Integer.parseInt(date.substring(5, 7)); 84 | int day = Integer.parseInt(date.substring(8, 10)); 85 | Calendar startingTime = Calendar.getInstance(); 86 | startingTime.set(year, month - 1, day, 0, 0, 0); 87 | return startingTime; 88 | } 89 | return null; 90 | } 91 | 92 | private long getDaysDiff(long startTime,long endTime) { 93 | long msDiff; 94 | if (endTime > startTime) { 95 | msDiff = endTime - startTime; 96 | } else { 97 | msDiff = startTime - endTime; 98 | } 99 | long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff); 100 | Log.e(TAG,"diff is "+ daysDiff); 101 | return daysDiff; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/homeScreen/HomeRouter.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.widget.AdapterView; 7 | 8 | import com.mycompany.flightstatuslistview.FlightModel; 9 | import com.mycompany.flightstatuslistview.boardingScreen.BoardingActivity; 10 | import com.mycompany.flightstatuslistview.pastTripScreen.PastTripActivity; 11 | 12 | 13 | import java.lang.ref.WeakReference; 14 | import java.util.Calendar; 15 | 16 | import util.CalendarUtil; 17 | 18 | /** 19 | * Created by mkaratadipalayam on 10/10/16. 20 | */ 21 | 22 | 23 | 24 | interface HomeRouterInput{ 25 | Intent determineNextScreen(int position); 26 | void passDataToNextScene(int position, Intent intent); 27 | } 28 | 29 | public class HomeRouter implements HomeRouterInput, AdapterView.OnItemClickListener { 30 | 31 | public static String TAG = HomeRouter.class.getSimpleName(); 32 | public WeakReference activity; 33 | private Calendar currentTime; 34 | 35 | 36 | public Calendar getCurrentTime() { 37 | if(currentTime == null) return Calendar.getInstance(); 38 | return currentTime; 39 | } 40 | public void setCurrentTime(Calendar currentTime) { 41 | this.currentTime = currentTime; 42 | } 43 | 44 | 45 | 46 | @NonNull 47 | @Override 48 | public Intent determineNextScreen(int position) { 49 | //Based on the position or someother data decide what is the next scene 50 | 51 | FlightModel flight = activity.get().listOfVMFlights.get(position); 52 | Calendar startingTime = CalendarUtil.getCalendar(flight.startingTime); 53 | 54 | if(isFutureFlight(startingTime)) { 55 | return new Intent(activity.get(), BoardingActivity.class); 56 | } else { 57 | return new Intent(activity.get(), PastTripActivity.class); 58 | } 59 | } 60 | 61 | @Override 62 | public void passDataToNextScene(int position, Intent intent) { 63 | //Based on the position or someother data decide the data for the next scene 64 | FlightModel flight = activity.get().listOfVMFlights.get(position); 65 | intent.putExtra("flight",flight); 66 | } 67 | 68 | @Override 69 | public void onItemClick(AdapterView parent, View view, int position, long id) { 70 | // Log.e(TAG, "onItemClick() called with: parent = [" + parent + "], view = [" + view + "], position = [" + position + "], id = [" + id + "]"); 71 | Intent intent = determineNextScreen(position); 72 | passDataToNextScene(position, intent); 73 | activity.get().startActivity(intent); 74 | } 75 | 76 | private boolean isFutureFlight(Calendar startingTime){ 77 | long startTimeInMills = startingTime.getTimeInMillis(); 78 | long currentTimeInMills = getCurrentTime().getTimeInMillis(); 79 | return startTimeInMills >= currentTimeInMills; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/mycompany/flightstatuslistview/pastTripScreen/PastTripActivity.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.pastTripScreen; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.util.Log; 6 | import android.widget.TextView; 7 | 8 | import com.mycompany.flightstatuslistview.FlightModel; 9 | import com.mycompany.flightstatuslistview.R; 10 | 11 | 12 | /** 13 | * Created by mkaratadipalayam on 20/06/17. 14 | */ 15 | 16 | public class PastTripActivity extends AppCompatActivity { 17 | 18 | private static final String TAG = PastTripActivity.class.getSimpleName(); 19 | 20 | 21 | private FlightModel flightModel; 22 | 23 | TextView mPnrValue; 24 | private TextView mPassengerName; 25 | TextView mFlightCode; 26 | private TextView mDepartureCity; 27 | private TextView mArrivalCity; 28 | private TextView mBoardingTime; 29 | private TextView mDepartureTime; 30 | TextView mDepartureDate; 31 | private TextView mArrivalTime; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_past_trip); 37 | getSupportActionBar().hide(); 38 | flightModel = getIntent().getParcelableExtra("flight"); 39 | bindViews(); 40 | displayTripData(flightModel); 41 | } 42 | 43 | private void bindViews(){ 44 | mPassengerName = (TextView) findViewById(R.id.tv_passengerName); 45 | //mFlightCode = (TextView) findViewById(R.id.tv_flightNumberValue); 46 | mDepartureCity = (TextView) findViewById(R.id.tv_departureAirport); 47 | mArrivalCity = (TextView) findViewById(R.id.tv_arrivalAirport); 48 | mBoardingTime = (TextView) findViewById(R.id.tv_boardingTime); 49 | mDepartureTime = (TextView) findViewById(R.id.tv_departureTime); 50 | mArrivalTime = (TextView) findViewById(R.id.tv_arrivalTime); 51 | // mDepartureDate = (TextView) findViewById(R.id.tv_departureDate); 52 | 53 | } 54 | 55 | private void displayTripData(FlightModel fightModel) { 56 | Log.e(TAG, "displayBoardingData() called with: viewModel = [" + fightModel + "]"); 57 | // Deal with the data 58 | mPassengerName.setText("Mr. Mohan Karats"); 59 | // mFlightCode.setText(flightModel.flightName); 60 | mArrivalCity.setText(flightModel.arrivalCity); 61 | mArrivalTime.setText(flightModel.arrivalTime); 62 | mDepartureCity.setText(flightModel.departureCity); 63 | mDepartureTime.setText(flightModel.departureTime); 64 | // mBoardingTime.setText(flightModel.); 65 | // mDepartureDate.setText(flightModel.startingTime); 66 | 67 | 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/util/CalendarUtil.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.util.Calendar; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by mkaratadipalayam on 20/06/17. 10 | */ 11 | 12 | public class CalendarUtil { 13 | 14 | @NonNull 15 | public static Calendar getCalendar(String date) { 16 | //Date should be in the format YYYY/MM/DD if not return 17 | if (date != null && !date.isEmpty() && date.length() == 10 ) { 18 | int year = Integer.parseInt(date.substring(0, 4)); 19 | int month = Integer.parseInt(date.substring(5, 7)); 20 | int day = Integer.parseInt(date.substring(8, 10)); 21 | Calendar startingTime = Calendar.getInstance(); 22 | startingTime.set(year, month - 1, day, 0, 0, 0); 23 | return startingTime; 24 | } 25 | return null; 26 | } 27 | 28 | public static long getDaysDiff(long startTime,long endTime) { 29 | long msDiff; 30 | if (endTime > startTime) { 31 | msDiff = endTime - startTime; 32 | } else { 33 | msDiff = startTime - endTime; 34 | } 35 | // Log.e(TAG,"diff is "+ daysDiff); 36 | return TimeUnit.MILLISECONDS.toDays(msDiff); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_plan_landing.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_plan_takeoff.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_circle_stroke.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_rectangle_fill_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_rectangle_stroke.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_flight_boarding.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 15 | 16 | 27 | 28 | 38 | 39 | 50 | 51 | 62 | 63 | 75 | 76 | 86 | 87 | 97 | 98 | 108 | 109 | 120 | 121 | 132 | 133 | 145 | 146 | 147 | 148 | 158 | 159 | 168 | 169 | 179 | 180 | 181 | 190 | 191 | 201 | 202 | 212 | 213 | 222 | 223 | 235 | 248 | 249 | 265 | 266 | 277 | 278 | 289 | 290 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_flight_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 22 | 23 | 30 | 31 | 32 | 37 | 44 | 51 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_past_trip.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | 30 | 31 | 41 | 42 | 52 | 53 | 62 | 63 | 72 | 73 | 85 | 86 | 98 | 99 | 110 | 111 | 122 | 123 | 133 | 134 | 143 | 144 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /app/src/main/res/layout/cell_flight_status.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 19 | 20 | 27 | 28 | 29 | 33 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/cell_trip_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 25 | 26 | 36 | 37 | 52 | 53 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/src/main/res/layout/flight_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 18 | 19 | 26 | 27 | 28 | 32 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmmraj/android-clean-code/84e7f0ce4126991dd0bf660a65f0dd60d89427a9/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmmraj/android-clean-code/84e7f0ce4126991dd0bf660a65f0dd60d89427a9/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmmraj/android-clean-code/84e7f0ce4126991dd0bf660a65f0dd60d89427a9/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmmraj/android-clean-code/84e7f0ce4126991dd0bf660a65f0dd60d89427a9/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmmraj/android-clean-code/84e7f0ce4126991dd0bf660a65f0dd60d89427a9/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/plan_landing.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/plan_takeoff.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3f51b5 4 | #303f9f 5 | #FF4081 6 | #807F80 7 | #80ff0000 8 | #3FBAEB 9 | 10 | #7986CB 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | My Trips 3 | Trip Detail 4 | PASSENGER 5 | MR. MOHAN KARATS 6 | BLR 7 | CJB 8 | 9F 2465 9 | BOARDING TIME 10 | 02:10 PM 11 | DEPARTURE 12 | 02:40 PM 13 | 03:10 PM 14 | ARRIVAL 15 | 00:15 16 | BOARDING IN 17 | TERMINAL 18 | GATE 19 | SEAT 20 | 1 21 | 6A 22 | 01A 23 | DEPARTURE DATE 24 | 2018 Jan 15 25 | Depature Airport Code 26 | Arrival Airport Code 27 | To Airport 28 | FLIGHT 29 | PNR 30 | Z1Y2X3 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Base application theme. 4 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/test/java/com/mycompany/flightstatuslistview/homeScreen/HomeActivityUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import org.junit.After; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.robolectric.Robolectric; 9 | import org.robolectric.RobolectricTestRunner; 10 | 11 | /** 12 | * Created by mkaratadipalayam on 13/10/16. 13 | */ 14 | 15 | @RunWith(RobolectricTestRunner.class) 16 | public class HomeActivityUnitTest { 17 | @Before 18 | public void setUp(){} 19 | @After 20 | public void tearDown(){} 21 | 22 | 23 | @Test 24 | public void HomeActivity_ShouldNOT_be_Null(){ 25 | //Given 26 | HomeActivity activity = Robolectric.setupActivity(HomeActivity.class); 27 | //When 28 | 29 | // Then 30 | Assert.assertNotNull(activity); 31 | } 32 | 33 | @Test 34 | public void onCreate_shouldCall_fetchHomeMetaData(){ 35 | //Given 36 | HomeActivityOutputSpy homeActivityOutputSpy = new HomeActivityOutputSpy(); 37 | HomeActivity homeActivity = Robolectric.setupActivity(HomeActivity.class); 38 | // It must have called the onCreate earlier, 39 | // we are injecting the mock and calling the fetchMetaData to test our condition 40 | homeActivity.output = homeActivityOutputSpy; 41 | 42 | //When 43 | homeActivity.fetchMetaData(); 44 | 45 | //Then 46 | Assert.assertTrue(homeActivityOutputSpy.fetchHomeMetaDataIsCalled); 47 | } 48 | 49 | @Test 50 | public void onCreate_Calls_fetchHomeMetaData_withCorrectData(){ 51 | //Given 52 | HomeActivityOutputSpy homeActivityOutputSpy = new HomeActivityOutputSpy(); 53 | HomeActivity homeActivity = Robolectric.setupActivity(HomeActivity.class); 54 | homeActivity.output = homeActivityOutputSpy; 55 | 56 | //When 57 | homeActivity.fetchMetaData(); 58 | 59 | //Then 60 | Assert.assertNotNull(homeActivity); 61 | Assert.assertTrue(homeActivityOutputSpy.homeRequestCopy.isFutureTrips); 62 | } 63 | 64 | 65 | 66 | private class HomeActivityOutputSpy implements HomeInteractorInput { 67 | 68 | boolean fetchHomeMetaDataIsCalled = false; 69 | HomeRequest homeRequestCopy; 70 | @Override 71 | public void fetchHomeMetaData(HomeRequest request) { 72 | fetchHomeMetaDataIsCalled = true; 73 | homeRequestCopy = request; 74 | } 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/test/java/com/mycompany/flightstatuslistview/homeScreen/HomeInteractorUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.mycompany.flightstatuslistview.ArrayEmptyException; 6 | import com.mycompany.flightstatuslistview.BuildConfig; 7 | import com.mycompany.flightstatuslistview.FlightModel; 8 | 9 | import org.junit.After; 10 | import org.junit.Assert; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.robolectric.RobolectricTestRunner; 15 | import org.robolectric.RobolectricTestRunner; 16 | import org.robolectric.annotation.Config; 17 | 18 | import java.util.ArrayList; 19 | 20 | /** 21 | * Created by mkaratadipalayam on 12/10/16. 22 | */ 23 | @RunWith(RobolectricTestRunner.class) 24 | public class HomeInteractorUnitTest { 25 | @Before 26 | public void setUp(){ 27 | 28 | } 29 | @After 30 | public void tearDown(){ 31 | 32 | } 33 | 34 | @Test 35 | public void fetchHomeMetaData_with_vaildInput_shouldCall_presentHomeMetaData(){ 36 | //Given 37 | HomeInteractor homeInteractor = new HomeInteractor(); 38 | HomeRequest homeRequest = new HomeRequest(); 39 | homeRequest.isFutureTrips = true; 40 | HomePresenterInputSpy homePresenterInputSpy = new HomePresenterInputSpy(); 41 | homeInteractor.output = homePresenterInputSpy; 42 | //When 43 | homeInteractor.fetchHomeMetaData(homeRequest); 44 | 45 | //Then 46 | Assert.assertTrue("When the valid input is passed to HomeInteractor " + 47 | "Then presentHomeMetaData should be called", 48 | homePresenterInputSpy.presentHomeMetaDataIsCalled); 49 | } 50 | 51 | @Test 52 | public void fetchHomeMetaData_with_vaildInput_FutureTrip_shouldCall_Worker_getFutureTrips(){ 53 | //Given 54 | HomeInteractor homeInteractor = new HomeInteractor(); 55 | HomeRequest homeRequest = new HomeRequest(); 56 | homeRequest.isFutureTrips = true; 57 | 58 | //Setup TestDoubles 59 | homeInteractor.output = new HomePresenterInputSpy(); 60 | FlightWorkerInputSpy flightWorkerInputSpy = new FlightWorkerInputSpy(); 61 | homeInteractor.setFlightWorkerInput(flightWorkerInputSpy); 62 | 63 | //When 64 | homeInteractor.fetchHomeMetaData(homeRequest); 65 | 66 | //Then 67 | Assert.assertTrue("When the input is passed to HomeInteractor is FutureTrip" + 68 | "Then getFutureFlights should be called in Worker", 69 | flightWorkerInputSpy.isgetFutureFlightsMethodCalled); 70 | } 71 | 72 | @Test 73 | public void fetchHomeMetaData_with_vaildInput_PastTrip_shouldCall_Worker_getPastTrips(){ 74 | //Given 75 | HomeInteractor homeInteractor = new HomeInteractor(); 76 | HomeRequest homeRequest = new HomeRequest(); 77 | homeRequest.isFutureTrips = false; 78 | 79 | //Setup TestDoubles 80 | homeInteractor.output = new HomePresenterInputSpy(); 81 | FlightWorkerInputSpy flightWorkerInputSpy = new FlightWorkerInputSpy(); 82 | homeInteractor.setFlightWorkerInput(flightWorkerInputSpy); 83 | 84 | //When 85 | homeInteractor.fetchHomeMetaData(homeRequest); 86 | 87 | //Then 88 | Assert.assertTrue("When the input is passed to HomeInteractor is FutureTrip" + 89 | "Then getFutureFlights should be called in Worker", 90 | flightWorkerInputSpy.isgetPastFlightsMethodCalled); 91 | } 92 | 93 | 94 | @Test(expected = ArrayEmptyException.class) 95 | public void fetchHomeMetaData_fetchingNull_shouldThrowArrayEmptyException(){ 96 | //Given 97 | HomeInteractor homeInteractor = new HomeInteractor(); 98 | HomeRequest homeRequest = new HomeRequest(); 99 | homeRequest.isFutureTrips = false; 100 | 101 | //Setup TestDoubles 102 | homeInteractor.output = new HomePresenterInputSpy(); 103 | FlightWorkerInputReturnNullSpy flightWorkerInputReturnNullSpy = new FlightWorkerInputReturnNullSpy(); 104 | homeInteractor.setFlightWorkerInput(flightWorkerInputReturnNullSpy); 105 | 106 | //When 107 | homeInteractor.fetchHomeMetaData(homeRequest); 108 | 109 | //Then 110 | // // Check for ArrayEmptyException -- See this method Annotation 111 | } 112 | 113 | private class HomePresenterInputSpy implements HomePresenterInput { 114 | 115 | boolean presentHomeMetaDataIsCalled = false; 116 | HomeResponse homeResponseCopy; 117 | @Override 118 | public void presentHomeMetaData(HomeResponse response) { 119 | presentHomeMetaDataIsCalled = true; 120 | homeResponseCopy = response; 121 | } 122 | } 123 | 124 | private class FlightWorkerInputSpy implements FlightWorkerInput { 125 | 126 | boolean isgetFutureFlightsMethodCalled = false; 127 | boolean isgetPastFlightsMethodCalled = false; 128 | 129 | @Override 130 | public ArrayList getFutureFlights() { 131 | isgetFutureFlightsMethodCalled = true; 132 | return getFlightModels(); 133 | } 134 | 135 | @Override 136 | public ArrayList getPastFlights() { 137 | isgetPastFlightsMethodCalled = true; 138 | return getFlightModels(); 139 | } 140 | 141 | @NonNull 142 | private ArrayList getFlightModels() { 143 | ArrayList flightsList = new ArrayList<>(); 144 | FlightModel flight1 = new FlightModel(); 145 | flight1.flightName = "9Z 231"; 146 | flight1.startingTime = "2016/10/31"; 147 | flight1.departureCity = "BLR"; 148 | flight1.arrivalCity = "CJB"; 149 | flight1.departureTime = "18:10"; 150 | flight1.arrivalTime = "19:00"; 151 | flightsList.add(flight1); 152 | return flightsList; 153 | } 154 | } 155 | 156 | private class FlightWorkerInputReturnNullSpy implements FlightWorkerInput { 157 | 158 | boolean isgetFlightsMethodCalled = false; 159 | boolean isgetPastFlightsMethodCalled = false; 160 | 161 | @Override 162 | public ArrayList getFutureFlights() { 163 | isgetFlightsMethodCalled = true; 164 | return null; 165 | } 166 | 167 | @Override 168 | public ArrayList getPastFlights() { 169 | isgetPastFlightsMethodCalled = true; 170 | return null; 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /app/src/test/java/com/mycompany/flightstatuslistview/homeScreen/HomePresenterUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | import android.util.Log; 4 | 5 | import com.mycompany.flightstatuslistview.FlightModel; 6 | 7 | import org.junit.After; 8 | import org.junit.Assert; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.robolectric.RobolectricTestRunner; 13 | 14 | import java.lang.ref.WeakReference; 15 | import java.util.ArrayList; 16 | import java.util.Calendar; 17 | 18 | /** 19 | * Created by mkaratadipalayam on 11/10/16. 20 | */ 21 | @RunWith(RobolectricTestRunner.class) 22 | public class HomePresenterUnitTest { 23 | public static String TAG = HomePresenterUnitTest.class.getSimpleName(); 24 | 25 | @Before 26 | public void setUp(){ 27 | 28 | } 29 | @After 30 | public void tearDown(){ 31 | 32 | } 33 | 34 | @Test 35 | public void presentHomeMetaData_with_vaildInput_shouldCall_displayHomeMetaData(){ 36 | //Given 37 | HomePresenter homePresenter = new HomePresenter(); 38 | HomeResponse homeResponse = new HomeResponse(); 39 | homeResponse.listOfFlights = new FlightWorker().getFutureFlights(); 40 | 41 | HomeActivityInputSpy homeActivityInputSpy = new HomeActivityInputSpy(); 42 | homePresenter.output = new WeakReference(homeActivityInputSpy); 43 | 44 | //When 45 | homePresenter.presentHomeMetaData(homeResponse); 46 | 47 | //Then 48 | Assert.assertTrue("When the valid input is passed to HomePresenter Then displayHomeMetaData should be called", homeActivityInputSpy.isdisplayHomeMetaDataCalled); 49 | } 50 | 51 | @Test 52 | public void presentHomeMetaData_with_inVaildInput_shouldNotCall_displayHomeMetaData(){ 53 | //Given 54 | HomePresenter homePresenter = new HomePresenter(); 55 | HomeResponse homeResponse = new HomeResponse(); 56 | homeResponse.listOfFlights = null; 57 | 58 | HomeActivityInputSpy homeActivityInputSpy = new HomeActivityInputSpy(); 59 | homePresenter.output = new WeakReference(homeActivityInputSpy); 60 | 61 | //When 62 | homePresenter.presentHomeMetaData(homeResponse); 63 | 64 | //Then 65 | Assert.assertFalse("When the valid input is passed to HomePresenter Then displayHomeMetaData should NOT be called", homeActivityInputSpy.isdisplayHomeMetaDataCalled); 66 | } 67 | 68 | @Test 69 | public void verify_HomePresenter_getDaysDiff_is_CalcualtedCorrectly_ForFutureTrips(){ 70 | //Given 71 | HomePresenter homePresenter = new HomePresenter(); 72 | HomeResponse homeResponse = new HomeResponse(); 73 | 74 | ArrayList flightsList = new ArrayList<>(); 75 | 76 | FlightModel flight1 = new FlightModel(); 77 | flight1.flightName = "9Z 231"; 78 | flight1.startingTime = "2017/12/31"; 79 | flight1.departureCity = "BLR"; 80 | flight1.arrivalCity = "CJB"; 81 | flight1.departureTime = "18:10"; 82 | flight1.arrivalTime = "19:00"; 83 | flightsList.add(flight1); 84 | homeResponse.listOfFlights = flightsList; 85 | 86 | HomeActivityInputSpy homeActivityInputSpy = new HomeActivityInputSpy(); 87 | homePresenter.output = new WeakReference(homeActivityInputSpy); 88 | 89 | //When 90 | Calendar currentTime = Calendar.getInstance(); 91 | currentTime.set(2017,5,30,0,0,0); 92 | homePresenter.setCurrentTime(currentTime); 93 | homePresenter.presentHomeMetaData(homeResponse); 94 | 95 | //Then 96 | // "It has been " + daysDiff + " days since you flew"; 97 | String ExpectedText = "You have " + "184" + " days to fly"; 98 | String ActualText = homeActivityInputSpy.homeViewModelCopy.listOfFlights.get(0).noOfDaysToFly; 99 | Assert.assertEquals("When current date is 2016/10/12 & Flying Date is 2016/10/31 Then no of days should be 19",ExpectedText,ActualText); 100 | 101 | } 102 | 103 | @Test 104 | public void verify_HomePresenter_getDaysDiff_is_CalcualtedCorrectly_ForPastTrips(){ 105 | //Given 106 | HomePresenter homePresenter = new HomePresenter(); 107 | HomeResponse homeResponse = new HomeResponse(); 108 | 109 | ArrayList flightsList = new ArrayList<>(); 110 | 111 | FlightModel flight1 = new FlightModel(); 112 | flight1.flightName = "9Z 231"; 113 | flight1.startingTime = "2016/10/01"; 114 | flight1.departureCity = "BLR"; 115 | flight1.arrivalCity = "CJB"; 116 | flight1.departureTime = "18:10"; 117 | flight1.arrivalTime = "19:00"; 118 | 119 | flightsList.add(flight1); 120 | 121 | 122 | homeResponse.listOfFlights = flightsList; 123 | 124 | HomeActivityInputSpy homeActivityInputSpy = new HomeActivityInputSpy(); 125 | homePresenter.output = new WeakReference(homeActivityInputSpy); 126 | 127 | 128 | //When 129 | Calendar currentTime = Calendar.getInstance(); 130 | //currentTime.set(2017,5,30,0,0,0); 131 | currentTime.set(2017,5,30); 132 | Log.e(TAG, "verify_HomePresenter_getDaysDiff_is_CalcualtedCorrectly_ForPastTrips: "+currentTime.toString() ); 133 | homePresenter.setCurrentTime(currentTime); 134 | homePresenter.presentHomeMetaData(homeResponse); 135 | 136 | 137 | //Then 138 | // "It has been " + daysDiff + " days since you flew"; 139 | String ExpectedText = "It has been " + 272 + " days since you flew"; 140 | String ActualText = homeActivityInputSpy.homeViewModelCopy.listOfFlights.get(0).noOfDaysToFly; 141 | Assert.assertEquals("When current date is 2017/05/30 & Flying Date is 2016/10/01 Then no of days should be 271",ExpectedText,ActualText); 142 | 143 | } 144 | 145 | private class HomeActivityInputSpy implements HomeActivityInput { 146 | public boolean isdisplayHomeMetaDataCalled = false; 147 | public HomeViewModel homeViewModelCopy; 148 | @Override 149 | public void displayHomeMetaData(HomeViewModel homeViewModel) { 150 | isdisplayHomeMetaDataCalled = true; 151 | homeViewModelCopy = homeViewModel; 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /app/src/test/java/com/mycompany/flightstatuslistview/homeScreen/HomeRouterUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.flightstatuslistview.homeScreen; 2 | 3 | 4 | import android.content.Intent; 5 | 6 | import com.mycompany.flightstatuslistview.FlightViewModel; 7 | import com.mycompany.flightstatuslistview.boardingScreen.BoardingActivity; 8 | import com.mycompany.flightstatuslistview.pastTripScreen.PastTripActivity; 9 | 10 | import org.junit.After; 11 | import org.junit.Assert; 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.robolectric.Robolectric; 16 | import org.robolectric.RobolectricTestRunner; 17 | 18 | import java.lang.ref.WeakReference; 19 | import java.util.ArrayList; 20 | import java.util.Calendar; 21 | /** 22 | * Created by mkaratadipalayam on 28/05/17. 23 | */ 24 | 25 | @RunWith(RobolectricTestRunner.class) 26 | public class HomeRouterUnitTest { 27 | public static String TAG = HomeRouterUnitTest.class.getSimpleName(); 28 | 29 | @Before 30 | public void setUp(){ 31 | 32 | } 33 | @After 34 | public void tearDown(){ 35 | 36 | } 37 | 38 | @Test 39 | public void homeRouter_determineNextScreen_when_futureTripIs_Input() { 40 | //Given 41 | HomeRouter homeRouter = new HomeRouter(); 42 | ArrayList flightList = new ArrayList<>(); 43 | FlightViewModel flight1 = new FlightViewModel(); 44 | flight1.flightName = "9Z 231"; 45 | flight1.startingTime = "2017/12/31"; 46 | flight1.departureCity = "BLR"; 47 | flight1.arrivalCity = "CJB"; 48 | flight1.departureTime = "18:10"; 49 | flight1.arrivalTime = "19:00"; 50 | flightList.add(flight1); 51 | 52 | FlightViewModel flight2 = new FlightViewModel(); 53 | flight2.flightName = "9Z 222"; 54 | flight2.startingTime = "2016/12/31"; 55 | flight2.departureCity = "BLR"; 56 | flight2.arrivalCity = "CJB"; 57 | flight2.departureTime = "18:10"; 58 | flight2.arrivalTime = "19:00"; 59 | flightList.add(flight2); 60 | 61 | HomeActivity homeActivity = Robolectric.setupActivity(HomeActivity.class); 62 | homeActivity.listOfVMFlights = flightList; 63 | homeActivity.router = homeRouter; 64 | homeRouter.activity = new WeakReference(homeActivity); 65 | 66 | Calendar currentTime = Calendar.getInstance(); 67 | currentTime.set(2017,5,30,0,0,0); 68 | homeRouter.setCurrentTime(currentTime); 69 | 70 | 71 | //When - Futrure Trip is Input 72 | 73 | Intent intent = homeRouter.determineNextScreen(0); 74 | 75 | //Then 76 | String targetActivityName = intent.getComponent().getClassName(); 77 | Assert.assertEquals("When the future travel date is passed to HomeRouter" 78 | +" Then next Intent should be BoardingActivity",targetActivityName, BoardingActivity.class.getName()); 79 | } 80 | 81 | 82 | @Test 83 | public void homeRouter_determineNextScreen_when_pastTripIs_Input() { 84 | //Given 85 | HomeRouter homeRouter = new HomeRouter(); 86 | ArrayList flightList = new ArrayList<>(); 87 | FlightViewModel flight1 = new FlightViewModel(); 88 | flight1.flightName = "9Z 231"; 89 | flight1.startingTime = "2017/12/31"; 90 | flight1.departureCity = "BLR"; 91 | flight1.arrivalCity = "CJB"; 92 | flight1.departureTime = "18:10"; 93 | flight1.arrivalTime = "19:00"; 94 | flightList.add(flight1); 95 | 96 | FlightViewModel flight2 = new FlightViewModel(); 97 | flight2.flightName = "9Z 222"; 98 | flight2.startingTime = "2016/12/31"; 99 | flight2.departureCity = "BLR"; 100 | flight2.arrivalCity = "CJB"; 101 | flight2.departureTime = "18:10"; 102 | flight2.arrivalTime = "19:00"; 103 | flightList.add(flight2); 104 | 105 | HomeActivity homeActivity = Robolectric.setupActivity(HomeActivity.class); 106 | homeActivity.listOfVMFlights = flightList; 107 | homeActivity.router = homeRouter; 108 | homeRouter.activity = new WeakReference(homeActivity); 109 | 110 | Calendar currentTime = Calendar.getInstance(); 111 | currentTime.set(2017,5,30,0,0,0); 112 | homeRouter.setCurrentTime(currentTime); 113 | 114 | 115 | 116 | //When - Past Trip is Input 117 | Intent intent = homeRouter.determineNextScreen(1); 118 | 119 | //Then 120 | String targetActivityName = intent.getComponent().getClassName(); 121 | Assert.assertEquals("When the past travel date is passed to HomeRouter" 122 | +" Then next Intent should be PastTripActivity",targetActivityName, PastTripActivity.class.getName()); 123 | } 124 | 125 | 126 | 127 | } 128 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | google() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:3.2.0' 8 | 9 | // NOTE: Do not place your application dependencies here; they belong 10 | // in the individual module build.gradle files 11 | } 12 | } 13 | 14 | allprojects { 15 | String osName = System.getProperty("os.name").toLowerCase(); 16 | if (osName.contains("windows")) { 17 | buildDir = "C:/tmp/${rootProject.name}/${project.name}" 18 | } 19 | repositories { 20 | jcenter() 21 | google() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------