Fixing mockable in tests. Fixing update vehicles in search/report screen after changing locations. Fixinf locations sorting

This commit is contained in:
Selim Mustafaev 2024-10-12 12:40:42 +03:00
parent 2a8f1d921a
commit 5f634ba895
12 changed files with 411 additions and 98 deletions

View File

@ -37,8 +37,6 @@
7A14416E2C297F7C00E79018 /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A14416D2C297F7C00E79018 /* Coordinator.swift */; };
7A1441702C2998B200E79018 /* Formatters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A14416F2C2998B200E79018 /* Formatters.swift */; };
7A176DB22C43071A00999D6B /* ApiServiceStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A176DB12C43071A00999D6B /* ApiServiceStub.swift */; };
7A176DB72C432F8800999D6B /* Mockable in Frameworks */ = {isa = PBXBuildFile; productRef = 7A176DB62C432F8800999D6B /* Mockable */; };
7A176DB92C432F8800999D6B /* MockableTest in Frameworks */ = {isa = PBXBuildFile; productRef = 7A176DB82C432F8800999D6B /* MockableTest */; };
7A17CE4A2A2E820300626A6E /* UIStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A17CE492A2E820300626A6E /* UIStackView.swift */; };
7A17CE4C2A2E850200626A6E /* UISegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A17CE4B2A2E850200626A6E /* UISegmentedControl.swift */; };
7A1CF80529A41C66007962DA /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A1CF80429A41C66007962DA /* RealmSwift */; };
@ -59,6 +57,9 @@
7A3E30F32C18840600567704 /* ActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3E30F22C18840600567704 /* ActivityItemSource.swift */; };
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AA24360DC800E59687 /* Dated.swift */; };
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AC2436350B00E59687 /* SearchController.swift */; };
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322902CB2CC8A00085CF6 /* FiltersScreen.swift */; };
7A4322932CB2CCAA00085CF6 /* FiltersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322922CB2CCAA00085CF6 /* FiltersViewModel.swift */; };
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */; };
7A45FB382C27073700618694 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45FB372C27073700618694 /* StorageService.swift */; };
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
@ -159,6 +160,8 @@
7AC355592969746600889457 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC355582969746600889457 /* UIControl.swift */; };
7AC3555B296995B200889457 /* UIEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC3555A296995B200889457 /* UIEdgeInsets.swift */; };
7AC76D7B270083AE0084DB27 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC76D7A270083AE0084DB27 /* TextView.swift */; };
7ACBB91E2CB9B155005A5168 /* Mockable in Frameworks */ = {isa = PBXBuildFile; productRef = 7ACBB91D2CB9B155005A5168 /* Mockable */; };
7ACBB9202CB9B16C005A5168 /* Mockable in Frameworks */ = {isa = PBXBuildFile; productRef = 7ACBB91F2CB9B16C005A5168 /* Mockable */; };
7ADF23062C25B5BF002624FF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7ADF23052C25B5BF002624FF /* RealmSwift */; };
7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADF6C92250B954900F237B2 /* Navigation.swift */; };
7ADF6C95250D037700F237B2 /* ShowEventController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADF6C94250D037700F237B2 /* ShowEventController.swift */; };
@ -189,6 +192,8 @@
7AF6D2212677C1680086EA64 /* PagedResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */; };
7AF6D2282677C2DC0086EA64 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE30246B2FE400297C33 /* Constants.swift */; };
7AF6D22A2677C3AD0086EA64 /* Exportable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE8424D26109F78002F6B31 /* Exportable.swift */; };
7AF8606C2CB9B20C00954D2F /* Mockable in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF8606B2CB9B20C00954D2F /* Mockable */; };
7AF8606E2CB9B86300954D2F /* Mockable in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF8606D2CB9B86300954D2F /* Mockable */; };
7AFBE8C02C3024E5003C491D /* ACHud.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFBE8BF2C3024E5003C491D /* ACHud.swift */; };
7AFBE8C42C302561003C491D /* ACHudContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFBE8C32C302561003C491D /* ACHudContainer.swift */; };
7AFBE8CA2C3081C7003C491D /* ACProgressHud+Modifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFBE8C92C3081C7003C491D /* ACProgressHud+Modifiers.swift */; };
@ -308,6 +313,9 @@
7A3E30F22C18840600567704 /* ActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityItemSource.swift; sourceTree = "<group>"; };
7A3F07AA24360DC800E59687 /* Dated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dated.swift; sourceTree = "<group>"; };
7A3F07AC2436350B00E59687 /* SearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchController.swift; sourceTree = "<group>"; };
7A4322902CB2CC8A00085CF6 /* FiltersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersScreen.swift; sourceTree = "<group>"; };
7A4322922CB2CCAA00085CF6 /* FiltersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersViewModel.swift; sourceTree = "<group>"; };
7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersCoordinator.swift; sourceTree = "<group>"; };
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
7A45FB372C27073700618694 /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; };
7A52AB292580112E002CD910 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -451,6 +459,7 @@
7ADF23062C25B5BF002624FF /* RealmSwift in Frameworks */,
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
7AC3554A2969652F00889457 /* SwiftEntryKit in Frameworks */,
7ACBB91E2CB9B155005A5168 /* Mockable in Frameworks */,
7AF6D2042677C03B0086EA64 /* AutoCatCore.framework in Frameworks */,
7A35177B27E23F8800DC538C /* Eureka in Frameworks */,
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */,
@ -463,6 +472,7 @@
files = (
7AB5871D2C42C1CF00FA7B66 /* RealmSwift in Frameworks */,
7A2E6FA72C42B3AD00C40DA7 /* AutoCatCore.framework in Frameworks */,
7AF8606C2CB9B20C00954D2F /* Mockable in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -470,7 +480,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7A176DB92C432F8800999D6B /* MockableTest in Frameworks */,
7ACBB9202CB9B16C005A5168 /* Mockable in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -480,7 +490,7 @@
files = (
7A1CF80529A41C66007962DA /* RealmSwift in Frameworks */,
7AABB1F2267E9CC800D7AB32 /* SwiftDate in Frameworks */,
7A176DB72C432F8800999D6B /* Mockable in Frameworks */,
7AF8606E2CB9B86300954D2F /* Mockable in Frameworks */,
7A6C4D9E2C56BCA600982597 /* SwiftLocation in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -663,6 +673,7 @@
7A1441632C297E9800E79018 /* Screens */ = {
isa = PBXGroup;
children = (
7A43228F2CB2CC5D00085CF6 /* FiltersScreen */,
7A06E0AA2C706550005731AC /* SettingsScreen */,
7A1022752C557E3F00B84627 /* LocationPickerScreen */,
7A10226A2C551EA200B84627 /* LocationEditScreen */,
@ -713,6 +724,16 @@
path = Extensions;
sourceTree = "<group>";
};
7A43228F2CB2CC5D00085CF6 /* FiltersScreen */ = {
isa = PBXGroup;
children = (
7A4322902CB2CC8A00085CF6 /* FiltersScreen.swift */,
7A4322922CB2CCAA00085CF6 /* FiltersViewModel.swift */,
7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */,
);
path = FiltersScreen;
sourceTree = "<group>";
};
7A45FB362C2706D000618694 /* Services */ = {
isa = PBXGroup;
children = (
@ -1065,6 +1086,7 @@
7A35177A27E23F8800DC538C /* Eureka */,
7AC355492969652F00889457 /* SwiftEntryKit */,
7ADF23052C25B5BF002624FF /* RealmSwift */,
7ACBB91D2CB9B155005A5168 /* Mockable */,
);
productName = AutoCat;
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
@ -1089,6 +1111,7 @@
name = AutoCatCoreTests;
packageProductDependencies = (
7AB5871C2C42C1CF00FA7B66 /* RealmSwift */,
7AF8606B2CB9B20C00954D2F /* Mockable */,
);
productName = AutoCatCoreTests;
productReference = 7A2E6FA32C42B3AD00C40DA7 /* AutoCatCoreTests.xctest */;
@ -1112,7 +1135,7 @@
);
name = AutoCatTests;
packageProductDependencies = (
7A176DB82C432F8800999D6B /* MockableTest */,
7ACBB91F2CB9B16C005A5168 /* Mockable */,
);
productName = AutoCatTests;
productReference = 7AB587222C42D27F00FA7B66 /* AutoCatTests.xctest */;
@ -1136,8 +1159,8 @@
packageProductDependencies = (
7AABB1F1267E9CC800D7AB32 /* SwiftDate */,
7A1CF80429A41C66007962DA /* RealmSwift */,
7A176DB62C432F8800999D6B /* Mockable */,
7A6C4D9D2C56BCA600982597 /* SwiftLocation */,
7AF8606D2CB9B86300954D2F /* Mockable */,
);
productName = AutoCatCore;
productReference = 7AF6D1EF2677C03B0086EA64 /* AutoCatCore.framework */;
@ -1186,8 +1209,8 @@
7A35177927E23F8800DC538C /* XCRemoteSwiftPackageReference "Eureka" */,
7AC355482969652F00889457 /* XCRemoteSwiftPackageReference "SwiftEntryKit" */,
7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */,
7A176DB52C432F8800999D6B /* XCRemoteSwiftPackageReference "Mockable" */,
7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */,
7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */,
);
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
projectDirPath = "";
@ -1248,6 +1271,7 @@
7A961C6C2C4C3C8600CE2211 /* TextRowView.swift in Sources */,
7AEFC3BE2529D3CC00BADFB2 /* ConfigurableCell.swift in Sources */,
7A1022772C557EC400B84627 /* LocationPickerScreen.swift in Sources */,
7A4322932CB2CCAA00085CF6 /* FiltersViewModel.swift in Sources */,
7A5D7E0C2C71EB25002C17E7 /* ToggleRowView.swift in Sources */,
7A7158092C44087E00852088 /* OsagoCoordinator.swift in Sources */,
7A1441662C297EDE00E79018 /* NotesScreen.swift in Sources */,
@ -1326,8 +1350,10 @@
7AFBE8C42C302561003C491D /* ACHudContainer.swift in Sources */,
7AC3555B296995B200889457 /* UIEdgeInsets.swift in Sources */,
7A06E0AC2C7065AC005731AC /* SettingsScreen.swift in Sources */,
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */,
7A7158002C43EA6900852088 /* OwnersScreen.swift in Sources */,
7A1441702C2998B200E79018 /* Formatters.swift in Sources */,
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */,
7ADF6C95250D037700F237B2 /* ShowEventController.swift in Sources */,
7A71580C2C44453200852088 /* AdsScreen.swift in Sources */,
7A06E0B02C7065D8005731AC /* SettingsCoordinator.swift in Sources */,
@ -1623,7 +1649,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 135;
CURRENT_PROJECT_VERSION = 136;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
@ -1650,7 +1676,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 135;
CURRENT_PROJECT_VERSION = 136;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
@ -1893,14 +1919,6 @@
minimumVersion = 6.1.0;
};
};
7A176DB52C432F8800999D6B /* XCRemoteSwiftPackageReference "Mockable" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Kolos65/Mockable";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.0.9;
};
};
7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/realm/realm-swift.git";
@ -1949,6 +1967,14 @@
minimumVersion = 2.0.0;
};
};
7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Kolos65/Mockable";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.0.11;
};
};
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/onevcat/Kingfisher";
@ -1960,16 +1986,6 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
7A176DB62C432F8800999D6B /* Mockable */ = {
isa = XCSwiftPackageProductDependency;
package = 7A176DB52C432F8800999D6B /* XCRemoteSwiftPackageReference "Mockable" */;
productName = Mockable;
};
7A176DB82C432F8800999D6B /* MockableTest */ = {
isa = XCSwiftPackageProductDependency;
package = 7A176DB52C432F8800999D6B /* XCRemoteSwiftPackageReference "Mockable" */;
productName = MockableTest;
};
7A1CF80429A41C66007962DA /* RealmSwift */ = {
isa = XCSwiftPackageProductDependency;
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
@ -2010,6 +2026,16 @@
package = 7AC355482969652F00889457 /* XCRemoteSwiftPackageReference "SwiftEntryKit" */;
productName = SwiftEntryKit;
};
7ACBB91D2CB9B155005A5168 /* Mockable */ = {
isa = XCSwiftPackageProductDependency;
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;
productName = Mockable;
};
7ACBB91F2CB9B16C005A5168 /* Mockable */ = {
isa = XCSwiftPackageProductDependency;
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;
productName = Mockable;
};
7ADF23052C25B5BF002624FF /* RealmSwift */ = {
isa = XCSwiftPackageProductDependency;
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
@ -2020,6 +2046,16 @@
package = 7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = Kingfisher;
};
7AF8606B2CB9B20C00954D2F /* Mockable */ = {
isa = XCSwiftPackageProductDependency;
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;
productName = Mockable;
};
7AF8606D2CB9B86300954D2F /* Mockable */ = {
isa = XCSwiftPackageProductDependency;
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;
productName = Mockable;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 7A1146F523FDE7E500B424AF /* Project object */;

View File

@ -1,5 +1,5 @@
{
"originHash" : "ae480e95b5199c1834610abd8aa26a821694aa5167d41c0aceddc8513e267012",
"originHash" : "457694e6162dd513aa4b1f33a0e4319bbd6de88b35dc652bf9fa41e06ea431da",
"pins" : [
{
"identity" : "eureka",
@ -33,8 +33,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Kolos65/Mockable",
"state" : {
"revision" : "da977ecb20974c4b1cf185f5fd38771b2d4674fb",
"version" : "0.0.10"
"revision" : "a9e5e1d222035567069ed6fff8429c327229b5f6",
"version" : "0.0.11"
}
},
{
@ -51,8 +51,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/realm-core.git",
"state" : {
"revision" : "c2552e1d36867cb42b28130e894a81fc17081062",
"version" : "14.12.0"
"revision" : "e474a8d2270a8b12ac63ac9504e4757e39814b99",
"version" : "14.13.0"
}
},
{
@ -60,8 +60,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/realm-swift.git",
"state" : {
"revision" : "5221a83dc720823e3017493394d00d49ccf13446",
"version" : "10.52.3"
"revision" : "863498d37a9f0e72caa65963da9641d8cdfc8228",
"version" : "10.54.0"
}
},
{
"identity" : "swift-issue-reporting",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-issue-reporting",
"state" : {
"revision" : "770f990d3e4eececb57ac04a6076e22f8c97daeb",
"version" : "1.4.2"
}
},
{

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7AF6D1EE2677C03B0086EA64"
BuildableName = "AutoCatCore.framework"
BlueprintName = "AutoCatCore"
ReferencedContainer = "container:AutoCat.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7AF6D1EE2677C03B0086EA64"
BuildableName = "AutoCatCore.framework"
BlueprintName = "AutoCatCore"
ReferencedContainer = "container:AutoCat.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -12,217 +12,217 @@
<key>AutoCatCore.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
<integer>2</integer>
</dict>
<key>DifferenceKit (Playground) 1.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>9</integer>
</dict>
<key>DifferenceKit (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>10</integer>
</dict>
<key>DifferenceKit (Playground).xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>8</integer>
</dict>
<key>Eureka (Playground) 1.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>3</integer>
</dict>
<key>Eureka (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>4</integer>
</dict>
<key>Eureka (Playground) 3.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>18</integer>
</dict>
<key>Eureka (Playground) 4.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>19</integer>
</dict>
<key>Eureka (Playground) 5.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>21</integer>
</dict>
<key>Eureka (Playground) 6.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>23</integer>
</dict>
<key>Eureka (Playground) 7.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>25</integer>
</dict>
<key>Eureka (Playground) 8.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>27</integer>
</dict>
<key>Eureka (Playground).xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>2</integer>
<integer>3</integer>
</dict>
<key>GettingStarted (Playground) 1.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>16</integer>
</dict>
<key>GettingStarted (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>17</integer>
</dict>
<key>GettingStarted (Playground) 3.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>14</integer>
</dict>
<key>GettingStarted (Playground) 4.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>20</integer>
</dict>
<key>GettingStarted (Playground) 5.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>26</integer>
</dict>
<key>GettingStarted (Playground).xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>12</integer>
<integer>1</integer>
</dict>
<key>Rx (Playground) 1.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>6</integer>
</dict>
<key>Rx (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>7</integer>
</dict>
<key>Rx (Playground) 3.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>22</integer>
</dict>
<key>Rx (Playground) 4.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>24</integer>
</dict>
<key>Rx (Playground) 5.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>28</integer>
</dict>
<key>Rx (Playground).xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>5</integer>
</dict>
<key>SwiftDate (Playground) 1.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>13</integer>
</dict>
<key>SwiftDate (Playground) 2.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>15</integer>
</dict>
<key>SwiftDate (Playground) 3.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>29</integer>
</dict>
<key>SwiftDate (Playground) 4.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>30</integer>
</dict>
<key>SwiftDate (Playground) 5.xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>31</integer>
</dict>
<key>SwiftDate (Playground).xcscheme</key>
<dict>
<key>isShown</key>
<false />
<false/>
<key>orderHint</key>
<integer>11</integer>
<integer>4</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
@ -230,7 +230,12 @@
<key>7A1146FC23FDE7E500B424AF</key>
<dict>
<key>primary</key>
<true />
<true/>
</dict>
<key>7AF6D1EE2677C03B0086EA64</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>

View File

@ -59,6 +59,8 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
}
}
public var vehicleUpdated: ((VehicleDto) -> Void)?
private var pins: [EventPin] = []
override func viewDidLoad() {
@ -392,6 +394,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
}
self.vehicle?.events = vehicle.events.sorted { $0.date > $1.date }
self.vehicleUpdated?(vehicle)
HUD.hide()
return true

View File

@ -26,6 +26,10 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
self.form.allSections.forEach { $0.reload() }
self.navigationController?.setNavigationBarHidden(self.vehicle == nil, animated: false)
}
if let vehicle {
vehicleUpdated?(vehicle)
}
}
}
@ -42,6 +46,8 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
}
}
public var vehicleUpdated: ((VehicleDto) -> Void)?
// MARK: - Lifecycle
override func viewDidLoad() {
@ -83,6 +89,9 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource
let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "EventsController") as EventsController
controller.vehicle = self.vehicle
controller.vehicleUpdated = { vehicle in
self.vehicle = vehicle
}
self.navigationController?.pushViewController(controller, animated: true)
}

View File

@ -100,7 +100,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
}
// FIXME: Code duplication
func updateDetailController(with vehicle: VehicleDto) {
func updateDetailController(with vehicle: VehicleDto, indexPath: IndexPath) {
if let splitViewController = self.view.window?.rootViewController as? UISplitViewController
{
var detail: UINavigationController?
@ -115,6 +115,10 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
detail.popToRootViewController(animated: true)
let report = detail.viewControllers.first as? ReportController
report?.vehicle = vehicle
report?.vehicleUpdated = { vehicle in
self.datasource.set(item: vehicle, at: indexPath)
self.tableView.reloadData()
}
splitViewController.showDetailViewController(detail, sender: self)
//self.performSegue(withIdentifier: "OpenDetailSegue", sender: self)
}
@ -151,7 +155,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
let menu = UIMenu(children: [
UIAction(title: NSLocalizedString("Filter results", comment: ""),
image: UIImage(systemName: "line.horizontal.3.decrease"),
handler: { _ in self.showFilter() }),
handler: { [weak self] _ in Task { try? await self?.showFilter() } }),
UIAction(title: NSLocalizedString("Show on map", comment: ""),
image: UIImage(systemName: "map"),
handler: { _ in self.showOnMap() }),
@ -166,7 +170,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
}
@IBAction func onFilterTapped(_ sender: UIBarButtonItem) {
showFilter()
Task { try? await showFilter() }
}
@IBAction func onMapTapped(_ sender: UIBarButtonItem) {
@ -179,7 +183,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
updateSearchResults(with: filter)
}
func showFilter() {
func showFilter() async throws {
let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "FiltersController") as FiltersController
controller.filter = self.filter
@ -191,6 +195,15 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
self.updateSearchResults(with: self.filter)
}
self.navigationController?.pushViewController(controller, animated: true)
// if let navigationController = self.navigationController {
// let coordinator = FiltersCoordinator(navController: navigationController, filter: filter)
// filter = try await coordinator.start()
// datasource.setSortParameter(self.filter.sortBy ?? .updatedDate)
// filter.needReset = true
// filter.scope = SearchScope(rawValue: self.searchController.searchBar.selectedScopeButtonIndex) ?? .plateNumber
// updateSearchResults(with: self.filter)
// }
}
func showOnMap() {
@ -291,7 +304,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
}
}
datasource.set(item: newVehicle, at: indexPath)
updateDetailController(with: newVehicle)
updateDetailController(with: newVehicle, indexPath: indexPath)
} catch {
HUD.hide()
show(error: error)
@ -301,7 +314,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vehicle = self.datasource.item(at: indexPath)
self.updateDetailController(with: vehicle)
self.updateDetailController(with: vehicle, indexPath: indexPath)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {

View File

@ -0,0 +1,31 @@
//
// FiltersCoordinator.swift
// AutoCat
//
// Created by Selim Mustafaev on 06.10.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import AutoCatCore
import UIKit
@MainActor
class FiltersCoordinator: Coordinator {
let viewController: UINavigationController?
let filter: Filter
init(navController: UINavigationController, filter: Filter) {
self.viewController = navController
self.filter = filter
}
func start() async throws -> Filter {
let viewModel = FiltersViewModel(filter: filter)
let controller = CustomHostingController(rootView: FiltersScreen(viewModel: viewModel))
viewController?.pushViewController(controller, animated: true)
await controller.waitForDisappear()
return viewModel.filter
}
}

View File

@ -0,0 +1,47 @@
//
// FiltersScreen.swift
// AutoCat
//
// Created by Selim Mustafaev on 06.10.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import SwiftUI
import AutoCatCore
enum DetailScreen: Hashable {
case brand
case model
case color
case year
}
struct FiltersScreen: View {
@State var viewModel: FiltersViewModel
var body: some View {
Form {
Section("Main filters") {
NavigationLink(value: DetailScreen.brand) {
LabeledContent("Brand", value: viewModel.filter.brand ?? "Any")
}
LabeledContent("Model", value: viewModel.filter.model ?? "Any")
LabeledContent("Color", value: viewModel.filter.color ?? "Any")
LabeledContent("Year", value: viewModel.filter.year ?? "Any")
}
}
.navigationTitle("Filters")
.navigationBarItems(trailing: Button("Done", action: {
}))
.navigationDestination(for: DetailScreen.self) { _ in
EmptyView()
}
}
}
#Preview {
FiltersScreen(viewModel: .init(filter: Filter()))
}

View File

@ -0,0 +1,21 @@
//
// FiltersViewModel.swift
// AutoCat
//
// Created by Selim Mustafaev on 06.10.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import SwiftUI
import AutoCatCore
@MainActor
@Observable
class FiltersViewModel {
var filter: Filter
init(filter: Filter) {
self.filter = filter
}
}

View File

@ -97,11 +97,14 @@ extension VehicleDto: Decodable {
self.photos = try container.decodeIfPresent([VehiclePhotoDto].self, forKey: .photos) ?? []
self.ownershipPeriods = try container.decodeIfPresent([VehicleOwnershipPeriodDto].self, forKey: .ownershipPeriods) ?? []
self.events = try container.decodeIfPresent([VehicleEventDto].self, forKey: .events) ?? []
self.osagoContracts = try container.decodeIfPresent([OsagoDto].self, forKey: .osagoContracts) ?? []
self.ads = try container.decodeIfPresent([VehicleAdDto].self, forKey: .ads) ?? []
self.notes = try container.decodeIfPresent([VehicleNoteDto].self, forKey: .notes) ?? []
if let events = try container.decodeIfPresent([VehicleEventDto].self, forKey: .events) {
self.events = events.sorted { $0.date > $1.date }
}
// All vehicles received from API are synchronized by definition
self.synchronized = true
}

View File

@ -8,14 +8,14 @@
import Testing
import AutoCatCore
import MockableTest
import Mockable
@testable import AutoCat
@MainActor
final class NotesTests {
var storageServiceMock: StorageServiceMock
var apiServiceMock: ApiServiceMock
var storageServiceMock: MockStorageServiceProtocol
var apiServiceMock: MockApiServiceProtocol
var viewModel: NotesViewModel
@ -26,8 +26,8 @@ final class NotesTests {
lazy var unrecognizedVehicleWithNote: VehicleDto = .unrecognized.addNote(text: noteText)
init() {
storageServiceMock = StorageServiceMock()
apiServiceMock = ApiServiceMock()
storageServiceMock = MockStorageServiceProtocol()
apiServiceMock = MockApiServiceProtocol()
ServiceContainer.shared.register(StorageServiceProtocol.self, instance: storageServiceMock)
ServiceContainer.shared.register(ApiServiceProtocol.self, instance: apiServiceMock)
@ -35,22 +35,28 @@ final class NotesTests {
}
@Test("Add note (normal vehicle)")
func addNote() async throws {
func addNote() async {
// given(apiServiceMock)
// .add(notes: .any, to: .any).willReturn(vehicleWithNote)
print(vehicleWithNote)
given(apiServiceMock)
.add(notes: .any, to: .any)
.willReturn(vehicleWithNote)
given(storageServiceMock)
.updateVehicleIfExists(dto: .any)
.willReturn()
await apiServiceMock.setVehicle(vehicleWithNote)
viewModel.vehicle = .normal
await viewModel.addNote(text: noteText)
// verify(apiServiceMock)
// .add(notes: .any, to: .any).called(.once)
//
// verify(storageServiceMock)
// .addNote(text: .any, to: .any).called(.never)
// .updateVehicleIfExists(dto: .any).called(.once)
verify(apiServiceMock)
.add(notes: .any, to: .any).called(.once)
verify(storageServiceMock)
.addNote(text: .any, to: .any).called(.never)
.updateVehicleIfExists(dto: .any).called(.once)
#expect(viewModel.vehicle.notes.contains { $0.text == noteText })
#expect(viewModel.hud == nil)
@ -59,11 +65,21 @@ final class NotesTests {
@Test("Add note (unrecognized vehicle)")
func addNoteUnrecognized() async throws {
await storageServiceMock.setVehicle(vehicleWithNote)
given(storageServiceMock)
.addNote(text: .any, to: .any)
.willReturn(vehicleWithNote)
viewModel.vehicle = .unrecognized
await viewModel.addNote(text: noteText)
verify(apiServiceMock)
.add(notes: .any, to: .any).called(.never)
verify(storageServiceMock)
.addNote(text: .any, to: .any).called(.once)
.updateVehicleIfExists(dto: .any).called(.never)
#expect(viewModel.vehicle.notes.contains { $0.text == noteText })
#expect(viewModel.hud == nil)
}
@ -72,11 +88,27 @@ final class NotesTests {
func editNote() async throws {
let noteId = try #require(vehicleWithNote.notes.first?.id)
await apiServiceMock.setVehicle(.normal.addNote(text: noteTextModified, id: noteId))
let modifiedVehicle: VehicleDto = .normal.addNote(text: noteTextModified, id: noteId)
given(apiServiceMock)
.edit(note: .any)
.willReturn(modifiedVehicle)
given(storageServiceMock)
.updateVehicleIfExists(dto: .any)
.willReturn()
viewModel.vehicle = vehicleWithNote
await viewModel.editNote(id: noteId, text: noteTextModified)
verify(apiServiceMock)
.edit(note: .any).called(.once)
verify(storageServiceMock)
.editNote(id: .any, text: .any, for: .any).called(.never)
.updateVehicleIfExists(dto: .any).called(.once)
#expect(viewModel.vehicle.notes.contains { $0.text == noteTextModified })
#expect(viewModel.hud == nil)
}
@ -86,11 +118,22 @@ final class NotesTests {
let vehicle: VehicleDto = .unrecognized.addNote(text: noteText)
let noteId = try #require(vehicle.notes.first?.id)
await storageServiceMock.setVehicle(.unrecognized.addNote(text: noteTextModified, id: noteId))
given(storageServiceMock)
.editNote(id: .value(noteId), text: .value(noteTextModified), for: .any)
.willReturn(.unrecognized.addNote(text: noteTextModified, id: noteId))
viewModel.vehicle = vehicle
await viewModel.editNote(id: noteId, text: noteTextModified)
verify(apiServiceMock)
.edit(note: .any).called(.never)
verify(storageServiceMock)
.editNote(id: .any, text: .any, for: .any).called(.once)
.updateVehicleIfExists(dto: .any).called(.never)
#expect(viewModel.vehicle.notes.contains { $0.text == noteTextModified })
#expect(viewModel.hud == nil)
}
@ -98,12 +141,27 @@ final class NotesTests {
@Test("Delete note (normal vehicle)")
func deleteNote() async throws {
await apiServiceMock.setVehicle(.normal)
viewModel.vehicle = vehicleWithNote
let noteId = try #require(vehicleWithNote.notes.first?.id)
given(apiServiceMock)
.remove(note: .value(noteId))
.willReturn(.normal)
given(storageServiceMock)
.updateVehicleIfExists(dto: .any)
.willReturn()
viewModel.vehicle = vehicleWithNote
await viewModel.deleteNote(id: noteId)
verify(apiServiceMock)
.remove(note: .any).called(.once)
verify(storageServiceMock)
.deleteNote(id: .any, for: .any).called(.never)
.updateVehicleIfExists(dto: .any).called(.once)
#expect(!viewModel.vehicle.notes.contains { $0.text == noteText })
#expect(viewModel.hud == nil)
}
@ -111,12 +169,23 @@ final class NotesTests {
@Test("Delete note (unrecognized vehicle)")
func deleteNoteUnrecognized() async throws {
await storageServiceMock.setVehicle(.unrecognized)
viewModel.vehicle = unrecognizedVehicleWithNote
let noteId = try #require(unrecognizedVehicleWithNote.notes.first?.id)
given(storageServiceMock)
.deleteNote(id: .value(noteId), for: .any)
.willReturn(.unrecognized)
viewModel.vehicle = unrecognizedVehicleWithNote
await viewModel.deleteNote(id: noteId)
verify(apiServiceMock)
.remove(note: .any).called(.never)
verify(storageServiceMock)
.deleteNote(id: .value(noteId), for: .any).called(.once)
.updateVehicleIfExists(dto: .any).called(.never)
#expect(!viewModel.vehicle.notes.contains { $0.text == noteText })
#expect(viewModel.hud == nil)
}