This commit is contained in:
Justin Mazzocchi 2020-08-31 11:57:02 -07:00
parent 5f96f59ac3
commit 2ca0dfe251
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
47 changed files with 120 additions and 116 deletions

View file

@ -7,7 +7,8 @@ import Stubbing
extension AccountEndpoint: Stubbing { extension AccountEndpoint: Stubbing {
public func data(url: URL) -> Data? { public func data(url: URL) -> Data? {
switch self { switch self {
case .verifyCredentials: return try? Data(contentsOf: Bundle.module.url(forResource: "account", withExtension: "json")!) case .verifyCredentials: return try? Data(contentsOf: Bundle.module.url(forResource: "account",
withExtension: "json")!)
} }
} }
} }

View file

@ -12,13 +12,12 @@
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */; }; D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */; };
D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */; }; D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */; };
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41E224F8889700D55A2D /* AttachmentsView.swift */; }; D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41E224F8889700D55A2D /* AttachmentsView.swift */; };
D04FD74224D4AA34007D572D /* DevelopmentModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD74124D4AA34007D572D /* DevelopmentModels.swift */; }; D04FD74224D4AA34007D572D /* PreviewMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD74124D4AA34007D572D /* PreviewMocks.swift */; };
D052BBC724D749C800A80A7A /* RootViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBC624D749C800A80A7A /* RootViewModelTests.swift */; }; D052BBC724D749C800A80A7A /* RootViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBC624D749C800A80A7A /* RootViewModelTests.swift */; };
D065F53924D37E5100741304 /* CombineExpectations in Frameworks */ = {isa = PBXBuildFile; productRef = D065F53824D37E5100741304 /* CombineExpectations */; }; D065F53924D37E5100741304 /* CombineExpectations in Frameworks */ = {isa = PBXBuildFile; productRef = D065F53824D37E5100741304 /* CombineExpectations */; };
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; }; D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; };
D075C28524FCD41D00D35112 /* Services in Frameworks */ = {isa = PBXBuildFile; productRef = D075C28424FCD41D00D35112 /* Services */; }; D0BDF66724FD7CDA00C7FA1C /* ServiceLayer in Frameworks */ = {isa = PBXBuildFile; productRef = D0BDF66624FD7CDA00C7FA1C /* ServiceLayer */; };
D075C28724FCD92400D35112 /* Services in Frameworks */ = {isa = PBXBuildFile; productRef = D075C28624FCD92400D35112 /* Services */; }; D0BDF66B24FD7CEC00C7FA1C /* ServiceLayer in Frameworks */ = {isa = PBXBuildFile; productRef = D0BDF66A24FD7CEC00C7FA1C /* ServiceLayer */; };
D0ADCBF124FD05510062ACCE /* ServiceMocks in Frameworks */ = {isa = PBXBuildFile; productRef = D0ADCBF024FD05510062ACCE /* ServiceMocks */; };
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; }; D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; };
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; }; D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; };
D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */; }; D0BEB1FD24F9E4E5001B0F04 /* ListsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */; };
@ -62,6 +61,7 @@
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46F24F76169001EBDBB /* View+Extensions.swift */; }; D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46F24F76169001EBDBB /* View+Extensions.swift */; };
D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47024F76169001EBDBB /* Date+Extensions.swift */; }; D0C7D4DB24F7616A001EBDBB /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47024F76169001EBDBB /* Date+Extensions.swift */; };
D0C7D4DC24F7616A001EBDBB /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47124F76169001EBDBB /* Data+Extensions.swift */; }; D0C7D4DC24F7616A001EBDBB /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D47124F76169001EBDBB /* Data+Extensions.swift */; };
D0E2C1CE24FD7EE900854680 /* ServiceLayerMocks in Frameworks */ = {isa = PBXBuildFile; productRef = D0E2C1CD24FD7EE900854680 /* ServiceLayerMocks */; };
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E5361B24E3EB4D00FB1CE1 /* NotificationService.swift */; }; D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E5361B24E3EB4D00FB1CE1 /* NotificationService.swift */; };
D0E5362024E3EB4D00FB1CE1 /* Notification Service Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; D0E5362024E3EB4D00FB1CE1 /* Notification Service Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
D0ED1B6E24CE100C00B4899C /* AddIdentityViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0ED1B6D24CE100C00B4899C /* AddIdentityViewModelTests.swift */; }; D0ED1B6E24CE100C00B4899C /* AddIdentityViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0ED1B6D24CE100C00B4899C /* AddIdentityViewModelTests.swift */; };
@ -105,11 +105,11 @@
D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentViewModel.swift; sourceTree = "<group>"; }; D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentViewModel.swift; sourceTree = "<group>"; };
D01F41E224F8889700D55A2D /* AttachmentsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsView.swift; sourceTree = "<group>"; }; D01F41E224F8889700D55A2D /* AttachmentsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsView.swift; sourceTree = "<group>"; };
D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; }; D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; };
D04FD74124D4AA34007D572D /* DevelopmentModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevelopmentModels.swift; sourceTree = "<group>"; }; D04FD74124D4AA34007D572D /* PreviewMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewMocks.swift; sourceTree = "<group>"; };
D052BBC624D749C800A80A7A /* RootViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewModelTests.swift; sourceTree = "<group>"; }; D052BBC624D749C800A80A7A /* RootViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewModelTests.swift; sourceTree = "<group>"; };
D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D0666A2524C677B400F3F04B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; D0666A2524C677B400F3F04B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D075C28324FCD27300D35112 /* Services */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Services; sourceTree = "<group>"; }; D0BDF66524FD7A6400C7FA1C /* ServiceLayer */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ServiceLayer; sourceTree = "<group>"; };
D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; }; D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; };
D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingTableFooterView.swift; sourceTree = "<group>"; }; D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingTableFooterView.swift; sourceTree = "<group>"; };
D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsViewModel.swift; sourceTree = "<group>"; }; D0BEB1FC24F9E4E5001B0F04 /* ListsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsViewModel.swift; sourceTree = "<group>"; };
@ -169,9 +169,9 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D075C28524FCD41D00D35112 /* Services in Frameworks */, D0BDF66724FD7CDA00C7FA1C /* ServiceLayer in Frameworks */,
D0ADCBF124FD05510062ACCE /* ServiceMocks in Frameworks */,
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */, D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */,
D0E2C1CE24FD7EE900854680 /* ServiceLayerMocks in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -187,7 +187,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D075C28724FCD92400D35112 /* Services in Frameworks */, D0BDF66B24FD7CEC00C7FA1C /* ServiceLayer in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -217,7 +217,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D0C7D45224F76169001EBDBB /* Assets.xcassets */, D0C7D45224F76169001EBDBB /* Assets.xcassets */,
D0ED1BB224CE3A1600B4899C /* Development Assets */,
D0C7D46824F76169001EBDBB /* Extensions */, D0C7D46824F76169001EBDBB /* Extensions */,
D0666A7924C7745A00F3F04B /* Frameworks */, D0666A7924C7745A00F3F04B /* Frameworks */,
D0BFDAF524FC7C5300C86618 /* HTTP */, D0BFDAF524FC7C5300C86618 /* HTTP */,
@ -225,8 +224,9 @@
D0E0F1E424FC49FC002C04BF /* Mastodon */, D0E0F1E424FC49FC002C04BF /* Mastodon */,
D0C7D43824F76169001EBDBB /* Model */, D0C7D43824F76169001EBDBB /* Model */,
D0E5361A24E3EB4D00FB1CE1 /* Notification Service Extension */, D0E5361A24E3EB4D00FB1CE1 /* Notification Service Extension */,
D0ED1BB224CE3A1600B4899C /* Preview */,
D047FA8D24C3E21200AF17C5 /* Products */, D047FA8D24C3E21200AF17C5 /* Products */,
D075C28324FCD27300D35112 /* Services */, D0BDF66524FD7A6400C7FA1C /* ServiceLayer */,
D0C7D41D24F76169001EBDBB /* Supporting Files */, D0C7D41D24F76169001EBDBB /* Supporting Files */,
D0C7D45324F76169001EBDBB /* System */, D0C7D45324F76169001EBDBB /* System */,
D0666A2224C677B400F3F04B /* Tests */, D0666A2224C677B400F3F04B /* Tests */,
@ -383,12 +383,12 @@
path = "View Models"; path = "View Models";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D0ED1BB224CE3A1600B4899C /* Development Assets */ = { D0ED1BB224CE3A1600B4899C /* Preview */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D04FD74124D4AA34007D572D /* DevelopmentModels.swift */, D04FD74124D4AA34007D572D /* PreviewMocks.swift */,
); );
path = "Development Assets"; path = Preview;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
/* End PBXGroup section */ /* End PBXGroup section */
@ -412,8 +412,8 @@
name = Metatext; name = Metatext;
packageProductDependencies = ( packageProductDependencies = (
D06B492224D4611300642749 /* KingfisherSwiftUI */, D06B492224D4611300642749 /* KingfisherSwiftUI */,
D075C28424FCD41D00D35112 /* Services */, D0BDF66624FD7CDA00C7FA1C /* ServiceLayer */,
D0ADCBF024FD05510062ACCE /* ServiceMocks */, D0E2C1CD24FD7EE900854680 /* ServiceLayerMocks */,
); );
productName = "Metatext (iOS)"; productName = "Metatext (iOS)";
productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */; productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */;
@ -454,7 +454,7 @@
); );
name = "Notification Service Extension"; name = "Notification Service Extension";
packageProductDependencies = ( packageProductDependencies = (
D075C28624FCD92400D35112 /* Services */, D0BDF66A24FD7CEC00C7FA1C /* ServiceLayer */,
); );
productName = "Notification Service Extension"; productName = "Notification Service Extension";
productReference = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */; productReference = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */;
@ -586,7 +586,7 @@
D0C7D4CF24F7616A001EBDBB /* StatusViewModel.swift in Sources */, D0C7D4CF24F7616A001EBDBB /* StatusViewModel.swift in Sources */,
D0C7D4C724F7616A001EBDBB /* PostingReadingPreferencesViewModel.swift in Sources */, D0C7D4C724F7616A001EBDBB /* PostingReadingPreferencesViewModel.swift in Sources */,
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */, D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */,
D04FD74224D4AA34007D572D /* DevelopmentModels.swift in Sources */, D04FD74224D4AA34007D572D /* PreviewMocks.swift in Sources */,
D0C7D4D924F7616A001EBDBB /* KingfisherOptionsInfo+Extensions.swift in Sources */, D0C7D4D924F7616A001EBDBB /* KingfisherOptionsInfo+Extensions.swift in Sources */,
D0C7D4DC24F7616A001EBDBB /* Data+Extensions.swift in Sources */, D0C7D4DC24F7616A001EBDBB /* Data+Extensions.swift in Sources */,
D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */, D0BEB1FF24F9E5BB001B0F04 /* ListsView.swift in Sources */,
@ -760,7 +760,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "Supporting Files/Metatext.entitlements"; CODE_SIGN_ENTITLEMENTS = "Supporting Files/Metatext.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "Development\\ Assets"; DEVELOPMENT_ASSET_PATHS = Preview;
DEVELOPMENT_TEAM = 82HL67AXQ2; DEVELOPMENT_TEAM = 82HL67AXQ2;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = "Supporting Files/Info.plist"; INFOPLIST_FILE = "Supporting Files/Info.plist";
@ -786,7 +786,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "Supporting Files/Metatext.entitlements"; CODE_SIGN_ENTITLEMENTS = "Supporting Files/Metatext.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "Development\\ Assets"; DEVELOPMENT_ASSET_PATHS = Preview;
DEVELOPMENT_TEAM = 82HL67AXQ2; DEVELOPMENT_TEAM = 82HL67AXQ2;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = "Supporting Files/Info.plist"; INFOPLIST_FILE = "Supporting Files/Info.plist";
@ -971,17 +971,17 @@
package = D06B492124D4611300642749 /* XCRemoteSwiftPackageReference "Kingfisher" */; package = D06B492124D4611300642749 /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = KingfisherSwiftUI; productName = KingfisherSwiftUI;
}; };
D075C28424FCD41D00D35112 /* Services */ = { D0BDF66624FD7CDA00C7FA1C /* ServiceLayer */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = Services; productName = ServiceLayer;
}; };
D075C28624FCD92400D35112 /* Services */ = { D0BDF66A24FD7CEC00C7FA1C /* ServiceLayer */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = Services; productName = ServiceLayer;
}; };
D0ADCBF024FD05510062ACCE /* ServiceMocks */ = { D0E2C1CD24FD7EE900854680 /* ServiceLayerMocks */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = ServiceMocks; productName = ServiceLayerMocks;
}; };
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
}; };

View file

@ -3,7 +3,7 @@
import UserNotifications import UserNotifications
import CryptoKit import CryptoKit
import Mastodon import Mastodon
import Services import ServiceLayer
class NotificationService: UNNotificationServiceExtension { class NotificationService: UNNotificationServiceExtension {

View file

@ -4,8 +4,9 @@ import Foundation
import Combine import Combine
import HTTP import HTTP
import Mastodon import Mastodon
import Services import MastodonStubs
import ServiceMocks import ServiceLayer
import ServiceLayerMocks
// swiftlint:disable force_try // swiftlint:disable force_try
private let decoder = APIDecoder() private let decoder = APIDecoder()
@ -15,11 +16,13 @@ private let devIdentityID = UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E
private let devAccessToken = "DEVELOPMENT_ACCESS_TOKEN" private let devAccessToken = "DEVELOPMENT_ACCESS_TOKEN"
extension Account { extension Account {
static let development = try! decoder.decode(Account.self, from: Data(officialAccountJSON.utf8)) static let development = try! decoder.decode(Account.self,
from: AccountEndpoint.verifyCredentials.data(url: devInstanceURL)!)
} }
extension Instance { extension Instance {
static let development = try! decoder.decode(Instance.self, from: Data(officialInstanceJSON.utf8)) static let development = try! decoder.decode(Instance.self,
from: InstanceEndpoint.instance.data(url: devInstanceURL)!)
} }
extension AppEnvironment { extension AppEnvironment {

View file

@ -3,18 +3,18 @@
import PackageDescription import PackageDescription
let package = Package( let package = Package(
name: "Services", name: "ServiceLayer",
platforms: [ platforms: [
.iOS(.v14), .iOS(.v14),
.macOS(.v11) .macOS(.v11)
], ],
products: [ products: [
.library( .library(
name: "Services", name: "ServiceLayer",
targets: ["Services"]), targets: ["ServiceLayer"]),
.library( .library(
name: "ServiceMocks", name: "ServiceLayerMocks",
targets: ["ServiceMocks"]) targets: ["ServiceLayerMocks"])
], ],
dependencies: [ dependencies: [
.package(url: "https://github.com/groue/CombineExpectations.git", .upToNextMajor(from: "0.5.0")), .package(url: "https://github.com/groue/CombineExpectations.git", .upToNextMajor(from: "0.5.0")),
@ -23,13 +23,13 @@ let package = Package(
], ],
targets: [ targets: [
.target( .target(
name: "Services", name: "ServiceLayer",
dependencies: ["GRDB", "Mastodon"]), dependencies: ["GRDB", "Mastodon"]),
.target( .target(
name: "ServiceMocks", name: "ServiceLayerMocks",
dependencies: ["Services", .product(name: "MastodonStubs", package: "Mastodon")]), dependencies: ["ServiceLayer", .product(name: "MastodonStubs", package: "Mastodon")]),
.testTarget( .testTarget(
name: "ServicesTests", name: "ServiceLayerTests",
dependencies: ["ServiceMocks", "CombineExpectations"]) dependencies: ["CombineExpectations", "ServiceLayerMocks"])
] ]
) )

View file

@ -1,9 +1,9 @@
import Foundation import Foundation
import HTTP import HTTP
import Services import ServiceLayer
import Stubbing import Stubbing
extension AppEnvironment { public extension AppEnvironment {
static let mock = AppEnvironment( static let mock = AppEnvironment(
session: Session(configuration: .stubbing), session: Session(configuration: .stubbing),
webAuthSessionType: SuccessfulMockWebAuthSession.self, webAuthSessionType: SuccessfulMockWebAuthSession.self,

View file

@ -0,0 +1,42 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import ServiceLayer
public struct MockKeychainService {}
public extension MockKeychainService {
static func reset() {
items = [String: Data]()
}
}
extension MockKeychainService: KeychainService {
public static func setGenericPassword(data: Data, forAccount key: String, service: String) throws {
items[key] = data
}
public static func deleteGenericPassword(account: String, service: String) throws {
items[account] = nil
}
public static func getGenericPassword(account: String, service: String) throws -> Data? {
items[account]
}
public static func generateKeyAndReturnPublicKey(applicationTag: String, attributes: [String: Any]) throws -> Data {
fatalError("not implemented")
}
public static func getPrivateKey(applicationTag: String, attributes: [String: Any]) throws -> Data? {
fatalError("not implemented")
}
public static func deleteKey(applicationTag: String) throws {
fatalError("not implemented")
}
}
private extension MockKeychainService {
static var items = [String: Data]()
}

View file

@ -2,12 +2,12 @@
import Foundation import Foundation
class MockUserDefaults: UserDefaults { public class MockUserDefaults: UserDefaults {
convenience init() { public convenience init() {
self.init(suiteName: Self.suiteName)! self.init(suiteName: Self.suiteName)!
} }
override init?(suiteName suitename: String?) { public override init?(suiteName suitename: String?) {
guard let suitename = suitename else { return nil } guard let suitename = suitename else { return nil }
UserDefaults().removePersistentDomain(forName: suitename) UserDefaults().removePersistentDomain(forName: suitename)
@ -17,5 +17,5 @@ class MockUserDefaults: UserDefaults {
} }
private extension MockUserDefaults { private extension MockUserDefaults {
private static let suiteName = "com.metatext.metabolist.mock-user-defaults" private static let suiteName = "com.metabolist.metatext.mock-user-defaults"
} }

View file

@ -1,15 +1,15 @@
// Copyright © 2020 Metabolist. All rights reserved. // Copyright © 2020 Metabolist. All rights reserved.
import Foundation import Foundation
import Services import ServiceLayer
class MockWebAuthSession: WebAuthSession { public class MockWebAuthSession: WebAuthSession {
let completionHandler: WebAuthSessionCompletionHandler let completionHandler: WebAuthSessionCompletionHandler
let url: URL let url: URL
let callbackURLScheme: String? let callbackURLScheme: String?
var presentationContextProvider: WebAuthPresentationContextProviding? public var presentationContextProvider: WebAuthPresentationContextProviding?
required init( public required init(
url URL: URL, url URL: URL,
callbackURLScheme: String?, callbackURLScheme: String?,
completionHandler: @escaping WebAuthSessionCompletionHandler) { completionHandler: @escaping WebAuthSessionCompletionHandler) {
@ -18,7 +18,7 @@ class MockWebAuthSession: WebAuthSession {
self.completionHandler = completionHandler self.completionHandler = completionHandler
} }
func start() -> Bool { public func start() -> Bool {
completionHandler(completionHandlerURL, completionHandlerError) completionHandler(completionHandlerURL, completionHandlerError)
return true return true
@ -33,7 +33,7 @@ class MockWebAuthSession: WebAuthSession {
} }
} }
class SuccessfulMockWebAuthSession: MockWebAuthSession { public class SuccessfulMockWebAuthSession: MockWebAuthSession {
private let redirectURL: URL private let redirectURL: URL
required init( required init(
@ -60,7 +60,7 @@ class SuccessfulMockWebAuthSession: MockWebAuthSession {
} }
} }
class CanceledLoginMockWebAuthSession: MockWebAuthSession { public class CanceledLoginMockWebAuthSession: MockWebAuthSession {
override var completionHandlerError: Error? { override var completionHandlerError: Error? {
WebAuthSessionError(.canceledLogin) WebAuthSessionError(.canceledLogin)
} }

View file

@ -3,8 +3,8 @@
import XCTest import XCTest
import Combine import Combine
import CombineExpectations import CombineExpectations
@testable import Services @testable import ServiceLayer
@testable import ServiceMocks @testable import ServiceLayerMocks
class AuthenticationServiceTests: XCTestCase { class AuthenticationServiceTests: XCTestCase {
func testAuthentication() throws { func testAuthentication() throws {

View file

@ -1,42 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import Services
struct MockKeychainService {}
extension MockKeychainService {
static func reset() {
items = [String: Data]()
}
}
extension MockKeychainService: KeychainService {
static func setGenericPassword(data: Data, forAccount key: String, service: String) throws {
items[key] = data
}
static func deleteGenericPassword(account: String, service: String) throws {
items[account] = nil
}
static func getGenericPassword(account: String, service: String) throws -> Data? {
items[account]
}
static func generateKeyAndReturnPublicKey(applicationTag: String, attributes: [String: Any]) throws -> Data {
fatalError("not implemented")
}
static func getPrivateKey(applicationTag: String, attributes: [String: Any]) throws -> Data? {
fatalError("not implemented")
}
static func deleteKey(applicationTag: String) throws {
fatalError("not implemented")
}
}
private extension MockKeychainService {
static var items = [String: Data]()
}

View file

@ -1,7 +1,7 @@
// Copyright © 2020 Metabolist. All rights reserved. // Copyright © 2020 Metabolist. All rights reserved.
import SwiftUI import SwiftUI
import Services import ServiceLayer
@main @main
struct MetatextApp: App { struct MetatextApp: App {

View file

@ -7,7 +7,7 @@ import HTTP
import Mastodon import Mastodon
@testable import Metatext @testable import Metatext
import Services import ServiceLayer
class AddIdentityViewModelTests: XCTestCase { class AddIdentityViewModelTests: XCTestCase {
func testAddIdentity() throws { func testAddIdentity() throws {

View file

@ -3,7 +3,7 @@
import XCTest import XCTest
import Combine import Combine
import CombineExpectations import CombineExpectations
import Services import ServiceLayer
@testable import Metatext @testable import Metatext
class RootViewModelTests: XCTestCase { class RootViewModelTests: XCTestCase {

View file

@ -2,7 +2,7 @@
import Foundation import Foundation
import Combine import Combine
import Services import ServiceLayer
class AddIdentityViewModel: ObservableObject { class AddIdentityViewModel: ObservableObject {
@Published var urlFieldText = "" @Published var urlFieldText = ""

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
class EditFilterViewModel: ObservableObject { class EditFilterViewModel: ObservableObject {
@Published var filter: Filter @Published var filter: Filter

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
class FiltersViewModel: ObservableObject { class FiltersViewModel: ObservableObject {
@Published var activeFilters = [Filter]() @Published var activeFilters = [Filter]()

View file

@ -2,7 +2,7 @@
import Combine import Combine
import Foundation import Foundation
import Services import ServiceLayer
class IdentitiesViewModel: ObservableObject { class IdentitiesViewModel: ObservableObject {
@Published private(set) var identity: Identity @Published private(set) var identity: Identity

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
class ListsViewModel: ObservableObject { class ListsViewModel: ObservableObject {
@Published private(set) var lists = [MastodonList]() @Published private(set) var lists = [MastodonList]()

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
class NotificationTypesPreferencesViewModel: ObservableObject { class NotificationTypesPreferencesViewModel: ObservableObject {
@Published var pushSubscriptionAlerts: PushSubscription.Alerts @Published var pushSubscriptionAlerts: PushSubscription.Alerts

View file

@ -2,7 +2,7 @@
import Foundation import Foundation
import Combine import Combine
import Services import ServiceLayer
class PostingReadingPreferencesViewModel: ObservableObject { class PostingReadingPreferencesViewModel: ObservableObject {
@Published var preferences: Identity.Preferences @Published var preferences: Identity.Preferences

View file

@ -1,7 +1,7 @@
// Copyright © 2020 Metabolist. All rights reserved. // Copyright © 2020 Metabolist. All rights reserved.
import Foundation import Foundation
import Services import ServiceLayer
class PreferencesViewModel: ObservableObject { class PreferencesViewModel: ObservableObject {
let handle: String let handle: String

View file

@ -2,7 +2,7 @@
import Foundation import Foundation
import Combine import Combine
import Services import ServiceLayer
class RootViewModel: ObservableObject { class RootViewModel: ObservableObject {
@Published private(set) var tabNavigationViewModel: TabNavigationViewModel? @Published private(set) var tabNavigationViewModel: TabNavigationViewModel?

View file

@ -1,7 +1,7 @@
// Copyright © 2020 Metabolist. All rights reserved. // Copyright © 2020 Metabolist. All rights reserved.
import Foundation import Foundation
import Services import ServiceLayer
class SecondaryNavigationViewModel: ObservableObject { class SecondaryNavigationViewModel: ObservableObject {
@Published private(set) var identity: Identity @Published private(set) var identity: Identity

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
class StatusListViewModel: ObservableObject { class StatusListViewModel: ObservableObject {
@Published private(set) var statusIDs = [[String]]() @Published private(set) var statusIDs = [[String]]()

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
struct StatusViewModel { struct StatusViewModel {
let content: NSAttributedString let content: NSAttributedString

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
import Mastodon import Mastodon
import Services import ServiceLayer
class TabNavigationViewModel: ObservableObject { class TabNavigationViewModel: ObservableObject {
@Published private(set) var identity: Identity @Published private(set) var identity: Identity

View file

@ -2,7 +2,7 @@
import SwiftUI import SwiftUI
import KingfisherSwiftUI import KingfisherSwiftUI
import struct Services.Identity import struct ServiceLayer.Identity
struct IdentitiesView: View { struct IdentitiesView: View {
@StateObject var viewModel: IdentitiesViewModel @StateObject var viewModel: IdentitiesViewModel