Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: create local stores and UTS - WPB-12100 #2141

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from

Conversation

jullianm
Copy link
Contributor

@jullianm jullianm commented Nov 8, 2024

TaskWPB-12100 [iOS] Create remaining local stores and add UTs for all stores

Key points

This PR isolates tests for our storage layer (local stores) and revisits tests for all our existing repositories.
Missing local stores were also created so the storage logic could be moved out from related repositories.

BEFORE:

  • Local stores were indirectly tested through our repositories

AFTER:

  • Each local store is directly tested.
  • Mock local stores are injected into repositories, repositories tests were revisited consequently.

In addition:

  • Removes super.setUp() and super.tearDown() code from all tests
  • Ensures local stores know nothing about API objects (using model mappers)
  • Uses .mockID instances from WireTestingPackage
  • Harmonizes tests naming

Testing

  • Add dedicated tests for all local stores
  • Revisit repositories tests

Checklist

  • Title contains a reference JIRA issue number like [WPB-XXX].
  • Description is filled and free of optional paragraphs.
  • Adds/updates automated tests.

UI accessibility checklist

If your PR includes UI changes, please utilize this checklist:

  • Make sure you use the API for UI elements that support large fonts.
  • All colors are taken from WireDesign.ColorTheme or constructed using WireDesign.BaseColorPalette.
  • New UI elements have Accessibility strings for VoiceOver.

@echoes-hq echoes-hq bot added echoes: technical-roadmap Work contributing to the Technical Roadmap, to improve our velocity or reduce the technical debt. echoes/initiative: ios-sync-refactoring labels Nov 8, 2024
func storeConnection(
_ connectionPayload: Connection
_ connectionInfo: ConnectionInfo
Copy link
Contributor Author

@jullianm jullianm Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll see changes like this in this PR: storage layer should not be aware of API objects so we create a domain model between repository and local store, here's the steps:

  1. Repo will fetch API model from remote.
  2. Repo will prepare data for the local store by mapping it to a domain model
  3. Repo will pass this model to the local store
  4. Local store will rely that model to manipulate (fetch, update, create) NSManagedObject

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now, it looks like all NSManagedObjects or context are isolated to Local stores, right?
I wonder if they would be cases where we want to be more flexible : thinking about the save contexts strategy we discussed.

Or going even further isolate all this to a WireStorage package

@@ -70,7 +70,7 @@ public struct ConnectionsRepository: ConnectionsRepositoryProtocol {
await withThrowingTaskGroup(of: Void.self) { taskGroup in
for connection in connections {
taskGroup.addTask {
try await connectionsLocalStore.storeConnection(connection)
try await connectionsLocalStore.storeConnection(connection.toDomainModel())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepare data for the store by mapping it to a domain model (so the local store doesn't know about the API layer)

) async throws
}

public final class ConversationLabelsLocalStore: ConversationLabelsLocalStoreProtocol {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This store was created. Storage operations were moved out from the related repository.


}

final class FeatureConfigLocalStore: FeatureConfigLocalStoreProtocol {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This store was created. Storage operations were moved out from related repository.

let name: Feature.Name
let isEnabled: Bool
let shouldNotifyUser: Bool
}
Copy link
Contributor Author

@jullianm jullianm Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these models were encapsulated in the repository, it was moved out and dedicated files were created in the FeatureConfig folder.

let selfPermission: Int64?
let creatorID: UUID?
let creationDate: Date?
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as mentioned above, mapping API object to domain model to pass them to the local store

import WireDataModel

// sourcery: AutoMockable
public protocol TeamLocalStoreProtocol {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This store was created and storage operations were moved out from related repository

// along with this program. If not, see http://www.gnu.org/licenses/.
//

import WireAPI
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamModelMappings used to convert API objects to domain model.

import WireFoundation

// sourcery: AutoMockable
protocol UpdateEventsLocalStoreProtocol {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This store was created and storage operations moved out from related repository


import WireDataModel

public struct NewUserInfo: Sendable {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used to map API object User to domain model


import WireDataModel

public struct UserUpdateInfo: Sendable {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used to map API object UpdateUserEvent to domain model, probably these two models are quite similar and could be merged at some point or maybe it's better to have two separated models

from remoteClient: WireAPI.SelfUserClient,
isNewClient: Bool
) async throws

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code that was factored out a few weeks ago to the UserClients component


user.isPendingMetadataRefresh = false
}
}

// swiftlint:disable:next todo_requires_jira_link
// TODO: refactor, do not pass API object (WireAPI.UserClient) directly
public func updateUserClient(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same dead code that was factored out

import WireDataModel

// sourcery: AutoMockable
public protocol UserClientsLocalStoreProtocol {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This local store was created and storage operations moved out from related repo

Copy link
Contributor

github-actions bot commented Nov 8, 2024

Test Results

165 tests   165 ✅  7s ⏱️
 47 suites    0 💤
  1 files      0 ❌

Results for commit 3d9ee9d.

♻️ This comment has been updated with latest results.

)

static let conversationLabel2 = ConversationLabelInfo(
id: .mockID4,
Copy link
Contributor Author

@jullianm jullianm Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

across tests we now use UUID helpers from WireTestingPackage

}

override func setUp() async throws {
coreDataStackHelper = CoreDataStackHelper()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing super.setUp() and super.tearDown() across tests

XCTAssertEqual(result, true)
}

func testFetchFeature_It_Retrieves_Feature_With_Correct_Config() async throws {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

harmonizing all tests naming format

import XCTest
import WireTestingPackage

final class TeamLocalStoreTests: XCTestCase {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically all the local store tests is code that was moved out from repositories (with some adjustments sometimes)

@@ -16,7 +16,6 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import CoreData
import WireAPI
Copy link
Contributor Author

@jullianm jullianm Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This local store still uses a WireAPI.Conversation object I didn't do it in this PR because we still have conversation events to tackle but eventually it will be mapped to a domain model as well.

We also have a SystemMessage model and message creation related methods in this repo this will be removed (in another PR) now that we have a Message dedicated component (Repository and local store)

import WireTestingPackage
import XCTest

final class UpdateEventsLocalStoreTests: XCTestCase {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnxnguyen could you please check this one particularly, I've split up tests in both repo and local stores and I want to make sure I didn't break your tests. thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
echoes/initiative: ios-sync-refactoring echoes: technical-roadmap Work contributing to the Technical Roadmap, to improve our velocity or reduce the technical debt.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants