Skip to content

application that shows modularity in terms of vertical slice using Unit, Integeration , Snapshot and UI Tests

Notifications You must be signed in to change notification settings

abdahad1996/WorldOfPAYBACK

Repository files navigation

CI-iOS (I used up all my free credits)

Screenshot 2024-01-16 at 08 26 51

SUMMARY

THIS PROJECT HAS 2 FEATURE LAYERS I VIRTUALLY SEPARATED IN FOLDERS CALLED TRANSACTION AND TRANSACTION DETAILS . THE FEATURE LAYERS CONTAINS THEIR OWN USECASES, API LAYER and Presentation layer . IN THE APP FOLDER IS THE COMPOSITION AND NAVIGATION WHERE I COMPOSE THE OVERALL OBJECT GRAPH AND PASS IT TO THE SCENE DELEGATE TO RUN.

Screenshot 2024-01-18 at 14 07 09

WorldOfPAYBACK

💡 My Motivation for this was based on simulating a real world making sure I think of the design in a critical and scalable way backed by tests which was very fun to do.

  1. Installation Guide
  2. Demo Videos
  3. Requirements
  4. Tools
  5. Frameworks
  6. Concepts
  7. Architecture
    1. Overview
    2. Domain
      1. Transaction Feature
    3. Networking
    4. API Infra
    5. Presentation
    6. UI
    7. Main
  8. Testing Strategy
    1. Unit Tests
    2. Integration Tests
      1. End-to-End Tests
    3. Snapshot Tests
  9. CI/CD
  10. Security
    1. API key for TransactionApi

Thank you for reading and enjoy! 🚀

Installation Guide

1. Setup WorldOfPAYBACK

  • clone the project from the main branch and run the simulator.
  • Mock Server completes with success or failure by randomness.

2. Validate the setup

Test that everything is wired up correctly by running tests for CI_IOS targets to check the communication with both mocked backend and validate that all tests pass.

Tools

  • ✅ Xcode 15.0
  • ✅ swift-driver version: 1.87.1 Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1)

Frameworks

  • ✅ SwiftUI
  • ✅ Combine
  • ✅ Foundation
  • ✅ UIKit

Concepts

  • ✅ MVVM, Clean Architecture
  • ✅ Modular Design
  • ✅ SOLID Principles
  • ✅ TDD, Unit Testing, Integration Testing, Snapshot Testing, and UI Testing using Page Object Pattern
  • ✅ Dependency injection and Dependency Inversion
  • ✅ Composition Root, Decorator Patterns
  • ✅ Domain-Driven Design

Requirements

Please create a SwiftUI App based on the following User-Stories:

✅ As a user of the App, I want to see a list of (mocked) transactions. Each item in the list displays bookingDate, partnerDisplayName, transactionDetail.description, value.amount, and value.currency. (see attached JSON File)

✅ As a user of the App, I want to have the list of transactions sorted by bookingDate from newest (top) to oldest (bottom).

✅ As a user of the App, I want to get feedback when the loading of the transactions is ongoing or an Error occurs. (Just delay the mocked server response for 1-2 seconds and randomly fail it)

✅ As a user of the App, I want to see an error if the device is offline.

  • From the Apple docs: Always attempt to make a connection. Do not attempt to guess whether network service is available, and do not cache that determination. It’s common to see iOS codebases using SCNetworkReachability, NWPathMonitor, or third-party reachability frameworks to make decisions about whether they should make a network request or not. Unfortunately, such a process is not reliable and can lead to a bad customer experience.

hence i did not use SCNetworkReachability or NWPathMonitor and just have a generic Connection Error in case my request fails

✅ As a user of the App, I want to filter the list of transactions by category.

✅ As a user of the App, I want to see the sum of filtered transactions somewhere on the Transaction-list view. (Sum of value.amount)

✅ As a user of the App, I want to select a transaction and navigate to its details. The details view should just display partnerDisplayName and transactionDetail.description.

✅ As a user of the App, I like to see nice UI in general. However, for this coding challenge fancy UI is not required.

We can extend our functionality using the same concepts and below is an example of Vertical Slicing

features can be vertically sliced and composed in the main module by following dependency injection/inversion, clean architecture, and domain driven design which allows us to have decoupled modules and gives you the freedom to compose however you like. Makes the code more testable maintainable and soft making it easy to add new requirements. I added a general example of a design diagram below

Screenshot 2024-01-16 at 14 41 50

Simulation Environment

transition phase of moving from UIKit to SwiftUI.

  • I didn't start with swiftui but rather with scene delegate so I could try to mimic Simulation cause i know a lot of legacy code is in uikit and the transition to swiftUI would involve a lot of hosting view controllers.
  • navigation is a known issue in swiftui and decoupling it from the views is not ideal maybe with navigation stack it is but with the constrain of ios 16 so i prefer to use at the moment flows or coordinator with hosting view controllers to decouple the view from navigation .
  • I tried to compose swiftui views using multiple child views so we can easily reuse a view anywhere in the codebase if needed
  • i stuck to @state and @stateobjects and not the new @observable macro again due to ios version constraints

We use Reactive programming and are currently moving from a Rx-Swift to Combine. For asynchronous code we are moving to Swift Concurrency.

  • again keeping in mind the Simulation. I started out with closure for asynchronous code like networking backed by tests and then i provided the clients the option to use async await using the checkedthrowing api provided by apple . the goal is to let the clients use the new async await while slowly moving away from closure based syntax or delegate if you use that but i guess completion handlers are more common. its important to test your async concurrent code and this involves a difference here as with completion handlers it's very easy to use a spy and capture it and complete whenever and however you want but we don't have that luxury with async await so i moved from spying to stubbing .
  • i limited the use of combine to the presentation layer only for my view models.
  • ideally combine or any 3rd party frameworks shouldn't be coupled with your layers especially your domain layer . your domain layer shouldn't depend on anything to allow for decoupled code
  • if you want to decouple one layer more you can add in an adapter layer which would adapt bw your domain and presentation layer and this way your presentation and domain don't know about each other. The adapter lives in the composition root so it knows about both the layers . you can also use universal abstractions to move away from dependency injection and just compose .

We try to keep to as few external dependencies as possible. However, we use Swift Package Manager when we need to add a dependency.

keeping this point in mind i used spm only snapshot my views for regression using SnapshotTesting library and nothing else

We are using Jenkins to build, test and deploy our Apps.

i tried to use github actions to achive some sort CI

About

application that shows modularity in terms of vertical slice using Unit, Integeration , Snapshot and UI Tests

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages