-
Notifications
You must be signed in to change notification settings - Fork 15
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
base: develop
Are you sure you want to change the base?
Conversation
…ects in storage layer
func storeConnection( | ||
_ connectionPayload: Connection | ||
_ connectionInfo: ConnectionInfo |
There was a problem hiding this comment.
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:
- Repo will fetch API model from remote.
- Repo will prepare data for the local store by mapping it to a domain model
- Repo will pass this model to the local store
- Local store will rely that model to manipulate (fetch, update, create) NSManagedObject
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 | ||
} |
There was a problem hiding this comment.
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? | ||
} |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 | ||
|
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
Test Results165 tests 165 ✅ 7s ⏱️ Results for commit 3d9ee9d. ♻️ This comment has been updated with latest results. |
) | ||
|
||
static let conversationLabel2 = ConversationLabelInfo( | ||
id: .mockID4, |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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!
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:
AFTER:
In addition:
Testing
Checklist
[WPB-XXX]
.UI accessibility checklist
If your PR includes UI changes, please utilize this checklist: