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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
5846ABF62B4762A600FA6C76 /* PollingBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */; };
|
||||||
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; };
|
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; };
|
||||||
58E7561D2BE04C320088BB5D /* MoleculeComparisonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E7561C2BE04C320088BB5D /* MoleculeComparisonProtocol.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui_dev.xcconfig; sourceTree = "<group>"; };
|
||||||
@ -1558,6 +1560,7 @@
|
|||||||
children = (
|
children = (
|
||||||
583335662BF6DCD0001D90D7 /* UAD_page_model_2.json */,
|
583335662BF6DCD0001D90D7 /* UAD_page_model_2.json */,
|
||||||
583335622BF6509C001D90D7 /* UAD_page_model.json */,
|
583335622BF6509C001D90D7 /* UAD_page_model.json */,
|
||||||
|
5833356C2BFBF51C001D90D7 /* UAD_page_model_3.json */,
|
||||||
);
|
);
|
||||||
path = Modelling;
|
path = Modelling;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2740,6 +2743,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
583335672BF6DCD0001D90D7 /* UAD_page_model_2.json in Resources */,
|
583335672BF6DCD0001D90D7 /* UAD_page_model_2.json in Resources */,
|
||||||
|
5833356D2BFBF51C001D90D7 /* UAD_page_model_3.json in Resources */,
|
||||||
583335632BF6509C001D90D7 /* UAD_page_model.json in Resources */,
|
583335632BF6509C001D90D7 /* UAD_page_model.json in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@ -256,18 +256,14 @@ import MVMCore
|
|||||||
var behaviorUpdatedModels = [MoleculeModelProtocol]()
|
var behaviorUpdatedModels = [MoleculeModelProtocol]()
|
||||||
if var newTemplateModel = newPageModel as? TemplateModelProtocol {
|
if var newTemplateModel = newPageModel as? TemplateModelProtocol {
|
||||||
executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
|
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
|
updatedMolecules.forEach { molecule in
|
||||||
|
// Replace again in case there is a template level child.
|
||||||
if let replaced = try? newTemplateModel.replaceChildMolecule(with: molecule) {
|
if let replaced = try? newTemplateModel.replaceChildMolecule(with: molecule) {
|
||||||
// Only recognize the molecules that actually changed.
|
// Only recognize the molecules that actually changed.
|
||||||
if let replaced = replaced as? ParentMoleculeModelProtocol, let molecule = molecule as? ParentMoleculeModelProtocol {
|
debugLog("Behavior updated \(changes) in template model.")
|
||||||
let diffs: [MoleculeModelProtocol] = replaced.findAllTheirsNotEqual(against: molecule)
|
behaviorUpdatedModels.append(contentsOf: changes)
|
||||||
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.)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
debugLog("Failed to replace \(molecule) in the template model.")
|
debugLog("Failed to replace \(molecule) in the template model.")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ public extension PageBehaviorProtocol {
|
|||||||
|
|
||||||
public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
|
public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
|
||||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) -> [MoleculeModelProtocol]?
|
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 willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?)
|
||||||
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol)
|
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol)
|
||||||
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar)
|
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar)
|
||||||
@ -41,7 +42,11 @@ public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
|
|||||||
|
|
||||||
public extension PageMoleculeTransformationBehavior {
|
public extension PageMoleculeTransformationBehavior {
|
||||||
// All optional.
|
// 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 willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) {}
|
||||||
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {}
|
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {}
|
||||||
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar) {}
|
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar) {}
|
||||||
|
|||||||
@ -44,11 +44,10 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
Self.debugLog("Initializing for \((model as! ReplaceableMoleculeBehaviorModel).moleculeIds)")
|
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
|
self.delegateObject = delegateObject
|
||||||
modulesToListenFor = moleculeIds
|
|
||||||
|
|
||||||
let moleculeModels = moleculeIds.compactMap { moleculeId in
|
let moleculeModels = moleculeIds.compactMap { moleculeId in
|
||||||
do {
|
do {
|
||||||
return try delegateObject?.moleculeDelegate?.getModuleWithName(moleculeId)
|
return try delegateObject?.moleculeDelegate?.getModuleWithName(moleculeId)
|
||||||
} catch {
|
} catch {
|
||||||
@ -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)")
|
debugLog("attempting to replace \(moleculeModels.map { $0.id }) in \(rootMolecules)")
|
||||||
var hasReplacement = false
|
var changeList = [any MoleculeModelProtocol]()
|
||||||
let updatedRootMolecules = rootMolecules.map { rootMolecule in
|
let updatedRootMolecules = rootMolecules.map { rootMolecule in
|
||||||
|
|
||||||
// Top level check to return a new root molecule.
|
// Top level check to return a new root molecule.
|
||||||
if let updatedMolecule = moleculeModels.first(where: { rootMolecule.id == $0.id }) {
|
if let updatedMolecule = moleculeModels.first(where: { rootMolecule.id == $0.id }) {
|
||||||
guard !updatedMolecule.isEqual(to: rootMolecule) else {
|
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
|
return rootMolecule
|
||||||
}
|
}
|
||||||
debugLog("replacing \(rootMolecule) with \(updatedMolecule)")
|
debugLog("top replacing \(rootMolecule) with \(updatedMolecule)")
|
||||||
logUpdated(molecule: updatedMolecule)
|
logUpdated(molecule: updatedMolecule)
|
||||||
hasReplacement = true
|
changeList.append(updatedMolecule)
|
||||||
return updatedMolecule
|
return updatedMolecule
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,12 +88,12 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) {
|
if let replacedMolecule = try parentMolecule.replaceChildMolecule(with: newMolecule) {
|
||||||
guard !replacedMolecule.isEqual(to: newMolecule) else {
|
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.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
debugLog("replacing \(replacedMolecule) with \(newMolecule)")
|
debugLog("deep replacing \(replacedMolecule) with \(newMolecule)")
|
||||||
logUpdated(molecule: newMolecule)
|
logUpdated(molecule: newMolecule)
|
||||||
hasReplacement = true
|
changeList.append(newMolecule)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: String(describing: type(of: self)))!
|
let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: String(describing: type(of: self)))!
|
||||||
@ -106,6 +105,8 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior, Co
|
|||||||
}
|
}
|
||||||
return parentMolecule
|
return parentMolecule
|
||||||
}
|
}
|
||||||
|
let hasReplacement = !changeList.isEmpty
|
||||||
|
changes.append(contentsOf: changeList)
|
||||||
debugLog("replacing \(hasReplacement ? updatedRootMolecules.count : 0) molecules")
|
debugLog("replacing \(hasReplacement ? updatedRootMolecules.count : 0) molecules")
|
||||||
return hasReplacement ? updatedRootMolecules : nil
|
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 listTemplateModel1 = try JSONDecoder().decode(ListPageTemplateModel.self, from: getFileData("UAD_page_model"))
|
||||||
let listTemplateModel2 = 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 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) })
|
let results = listTemplateModel1.findFirst(in: listTemplateModel2, failing: { $0.isEqual(to: $1) })
|
||||||
XCTAssertFalse(results.matched)
|
XCTAssertFalse(results.matched)
|
||||||
@ -199,6 +200,9 @@ final class MVMCoreUITests: XCTestCase {
|
|||||||
XCTAssertTrue(results2.matched)
|
XCTAssertTrue(results2.matched)
|
||||||
XCTAssertFalse(listTemplateModel1.deepEquals(to: listTemplateModel3))
|
XCTAssertFalse(listTemplateModel1.deepEquals(to: listTemplateModel3))
|
||||||
XCTAssertTrue(listTemplateModel1.isDeeplyVisuallyEquivalent(to: listTemplateModel3))
|
XCTAssertTrue(listTemplateModel1.isDeeplyVisuallyEquivalent(to: listTemplateModel3))
|
||||||
|
|
||||||
|
let results3: [MoleculeModelProtocol] = listTemplateModel1.findAllTheirsNotEqual(against: listTemplateModel4)
|
||||||
|
XCTAssertTrue(results3.count == 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPageEqualityPerformance() throws {
|
func testPageEqualityPerformance() throws {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user