Digital PCT265 story PCT-135: Rewire to allow the page transformation behavior to list all changes performed to the model tree.
This commit is contained in:
parent
f74bea64c2
commit
d377ec84b7
@ -175,6 +175,7 @@
|
||||
583335632BF6509C001D90D7 /* UAD_page_model.json in Resources */ = {isa = PBXBuildFile; fileRef = 583335622BF6509C001D90D7 /* UAD_page_model.json */; };
|
||||
583335652BF6A5C3001D90D7 /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583335642BF6A5C3001D90D7 /* TestUtils.swift */; };
|
||||
583335672BF6DCD0001D90D7 /* UAD_page_model_2.json in Resources */ = {isa = PBXBuildFile; fileRef = 583335662BF6DCD0001D90D7 /* UAD_page_model_2.json */; };
|
||||
5833356D2BFBF51C001D90D7 /* UAD_page_model_3.json in Resources */ = {isa = PBXBuildFile; fileRef = 5833356C2BFBF51C001D90D7 /* UAD_page_model_3.json */; };
|
||||
5846ABF62B4762A600FA6C76 /* PollingBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */; };
|
||||
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; };
|
||||
58E7561D2BE04C320088BB5D /* MoleculeComparisonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E7561C2BE04C320088BB5D /* MoleculeComparisonProtocol.swift */; };
|
||||
@ -797,6 +798,7 @@
|
||||
583335622BF6509C001D90D7 /* UAD_page_model.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = UAD_page_model.json; sourceTree = "<group>"; };
|
||||
583335642BF6A5C3001D90D7 /* TestUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = "<group>"; };
|
||||
583335662BF6DCD0001D90D7 /* UAD_page_model_2.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = UAD_page_model_2.json; sourceTree = "<group>"; };
|
||||
5833356C2BFBF51C001D90D7 /* UAD_page_model_3.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = UAD_page_model_3.json; sourceTree = "<group>"; };
|
||||
5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PollingBehaviorModel.swift; sourceTree = "<group>"; };
|
||||
5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui.xcconfig; sourceTree = "<group>"; };
|
||||
5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui_dev.xcconfig; sourceTree = "<group>"; };
|
||||
@ -1558,6 +1560,7 @@
|
||||
children = (
|
||||
583335662BF6DCD0001D90D7 /* UAD_page_model_2.json */,
|
||||
583335622BF6509C001D90D7 /* UAD_page_model.json */,
|
||||
5833356C2BFBF51C001D90D7 /* UAD_page_model_3.json */,
|
||||
);
|
||||
path = Modelling;
|
||||
sourceTree = "<group>";
|
||||
@ -2740,6 +2743,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
583335672BF6DCD0001D90D7 /* UAD_page_model_2.json in Resources */,
|
||||
5833356D2BFBF51C001D90D7 /* UAD_page_model_3.json in Resources */,
|
||||
583335632BF6509C001D90D7 /* UAD_page_model.json in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@ -256,18 +256,14 @@ import MVMCore
|
||||
var behaviorUpdatedModels = [MoleculeModelProtocol]()
|
||||
if var newTemplateModel = newPageModel as? TemplateModelProtocol {
|
||||
executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
|
||||
if let updatedMolecules = behavior.onPageNew(rootMolecules: newTemplateModel.rootMolecules, delegateObjectIVar) {
|
||||
var changes = [any MoleculeModelProtocol]()
|
||||
if let updatedMolecules = behavior.onPageNew(rootMolecules: newTemplateModel.rootMolecules, delegateObjectIVar, changes: &changes) {
|
||||
updatedMolecules.forEach { molecule in
|
||||
// Replace again in case there is a template level child.
|
||||
if let replaced = try? newTemplateModel.replaceChildMolecule(with: molecule) {
|
||||
// Only recognize the molecules that actually changed.
|
||||
if let replaced = replaced as? ParentMoleculeModelProtocol, let molecule = molecule as? ParentMoleculeModelProtocol {
|
||||
let diffs: [MoleculeModelProtocol] = replaced.findAllTheirsNotEqual(against: molecule)
|
||||
debugLog("Behavior updated \(diffs) in template model.")
|
||||
behaviorUpdatedModels.append(contentsOf: diffs)
|
||||
} else if !replaced.isEqual(to: molecule) {
|
||||
debugLog("Behavior updated \(molecule) in template model.")
|
||||
behaviorUpdatedModels.append(molecule) // Need to specifically trace molecule updates here as replacements are modifying the original tree. (We don't have a deep copy.)
|
||||
}
|
||||
debugLog("Behavior updated \(changes) in template model.")
|
||||
behaviorUpdatedModels.append(contentsOf: changes)
|
||||
} else {
|
||||
debugLog("Failed to replace \(molecule) in the template model.")
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ public extension PageBehaviorProtocol {
|
||||
|
||||
public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) -> [MoleculeModelProtocol]?
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?, changes: inout [MoleculeModelProtocol]) -> [MoleculeModelProtocol]?
|
||||
func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?)
|
||||
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol)
|
||||
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar)
|
||||
@ -41,7 +42,11 @@ public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
|
||||
|
||||
public extension PageMoleculeTransformationBehavior {
|
||||
// All optional.
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) -> [MoleculeModelProtocol]? { return nil }
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) -> [MoleculeModelProtocol]? {
|
||||
var changes = [any MoleculeModelProtocol]()
|
||||
return onPageNew(rootMolecules: rootMolecules, delegateObject, changes: &changes)
|
||||
}
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?, changes: inout [MoleculeModelProtocol]) -> [MoleculeModelProtocol]? { return nil }
|
||||
func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) {}
|
||||
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {}
|
||||
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar) {}
|
||||
|
||||
@ -44,9 +44,8 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
Self.debugLog("Initializing for \((model as! ReplaceableMoleculeBehaviorModel).moleculeIds)")
|
||||
}
|
||||
|
||||
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) -> [MoleculeModelProtocol]? {
|
||||
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?, changes: inout [MoleculeModelProtocol]) -> [MoleculeModelProtocol]? {
|
||||
self.delegateObject = delegateObject
|
||||
modulesToListenFor = moleculeIds
|
||||
|
||||
let moleculeModels = moleculeIds.compactMap { moleculeId in
|
||||
do {
|
||||
@ -61,23 +60,23 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
}
|
||||
}
|
||||
|
||||
return findAndReplace(moleculeModels, in: rootMolecules)
|
||||
return findAndReplace(moleculeModels, in: rootMolecules, changes: &changes)
|
||||
}
|
||||
|
||||
fileprivate func findAndReplace(_ moleculeModels: [any MoleculeModelProtocol], in rootMolecules: [any MoleculeModelProtocol]) -> [any MoleculeModelProtocol]? {
|
||||
fileprivate func findAndReplace(_ moleculeModels: [any MoleculeModelProtocol], in rootMolecules: [any MoleculeModelProtocol], changes: inout [MoleculeModelProtocol]) -> [any MoleculeModelProtocol]? {
|
||||
debugLog("attempting to replace \(moleculeModels.map { $0.id }) in \(rootMolecules)")
|
||||
var hasReplacement = false
|
||||
var changeList = [any MoleculeModelProtocol]()
|
||||
let updatedRootMolecules = rootMolecules.map { rootMolecule in
|
||||
|
||||
// Top level check to return a new root molecule.
|
||||
if let updatedMolecule = moleculeModels.first(where: { rootMolecule.id == $0.id }) {
|
||||
guard !updatedMolecule.isEqual(to: rootMolecule) else {
|
||||
debugLog("molecule \(updatedMolecule) is the same as \(rootMolecule). skipping...")
|
||||
debugLog("top molecule \(updatedMolecule) is the same as \(rootMolecule). skipping...")
|
||||
return rootMolecule
|
||||
}
|
||||
debugLog("replacing \(rootMolecule) with \(updatedMolecule)")
|
||||
debugLog("top replacing \(rootMolecule) with \(updatedMolecule)")
|
||||
logUpdated(molecule: updatedMolecule)
|
||||
hasReplacement = true
|
||||
changeList.append(updatedMolecule)
|
||||
return updatedMolecule
|
||||
}
|
||||
|
||||
@ -89,12 +88,12 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) {
|
||||
guard !replacedMolecule.isEqual(to: newMolecule) else {
|
||||
// Note: Slight risk here of replacing the something in the original tree and misreporting that is it not replaced based on equality.
|
||||
debugLog("molecule \(newMolecule) is the same as \(replacedMolecule). skipping...")
|
||||
debugLog("deep molecule \(newMolecule) is the same as \(replacedMolecule). skipping...")
|
||||
return
|
||||
}
|
||||
debugLog("replacing \(replacedMolecule) with \(newMolecule)")
|
||||
debugLog("deep replacing \(replacedMolecule) with \(newMolecule)")
|
||||
logUpdated(molecule: newMolecule)
|
||||
hasReplacement = true
|
||||
changeList.append(newMolecule)
|
||||
}
|
||||
} catch {
|
||||
let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: String(describing: type(of: self)))!
|
||||
@ -106,6 +105,8 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
||||
}
|
||||
return parentMolecule
|
||||
}
|
||||
let hasReplacement = !changeList.isEmpty
|
||||
changes.append(contentsOf: changeList)
|
||||
debugLog("replacing \(hasReplacement ? updatedRootMolecules.count : 0) molecules")
|
||||
return hasReplacement ? updatedRootMolecules : nil
|
||||
}
|
||||
|
||||
1243
MVMCoreUITests/JSON/Modelling/UAD_page_model_3.json
Normal file
1243
MVMCoreUITests/JSON/Modelling/UAD_page_model_3.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -189,6 +189,7 @@ final class MVMCoreUITests: XCTestCase {
|
||||
let listTemplateModel1 = try JSONDecoder().decode(ListPageTemplateModel.self, from: getFileData("UAD_page_model"))
|
||||
let listTemplateModel2 = try JSONDecoder().decode(ListPageTemplateModel.self, from: getFileData("UAD_page_model"))
|
||||
let listTemplateModel3 = try JSONDecoder().decode(ListPageTemplateModel.self, from: getFileData("UAD_page_model_2"))
|
||||
let listTemplateModel4 = try JSONDecoder().decode(ListPageTemplateModel.self, from: getFileData("UAD_page_model_3"))
|
||||
|
||||
let results = listTemplateModel1.findFirst(in: listTemplateModel2, failing: { $0.isEqual(to: $1) })
|
||||
XCTAssertFalse(results.matched)
|
||||
@ -199,6 +200,9 @@ final class MVMCoreUITests: XCTestCase {
|
||||
XCTAssertTrue(results2.matched)
|
||||
XCTAssertFalse(listTemplateModel1.deepEquals(to: listTemplateModel3))
|
||||
XCTAssertTrue(listTemplateModel1.isDeeplyVisuallyEquivalent(to: listTemplateModel3))
|
||||
|
||||
let results3: [MoleculeModelProtocol] = listTemplateModel1.findAllTheirsNotEqual(against: listTemplateModel4)
|
||||
XCTAssertTrue(results3.count == 2)
|
||||
}
|
||||
|
||||
func testPageEqualityPerformance() throws {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user