diff --git a/CCMenu.xcodeproj/project.pbxproj b/CCMenu.xcodeproj/project.pbxproj index 40a92ab..bf04c91 100644 --- a/CCMenu.xcodeproj/project.pbxproj +++ b/CCMenu.xcodeproj/project.pbxproj @@ -62,7 +62,6 @@ 03BD7EDB2598ED9B000F9495 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 03BD7EDA2598ED9B000F9495 /* Credits.rtf */; }; 03BD7EFA259A180C000F9495 /* NSImageExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BD7EF9259A180C000F9495 /* NSImageExtension.swift */; }; 03CC11EA2652F49100130833 /* ServerMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03CC11E92652F49100130833 /* ServerMonitor.swift */; }; - 03CC11EC2652F58B00130833 /* ServerMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03CC11EB2652F58B00130833 /* ServerMonitorTests.swift */; }; 03CC11EE2652F6B900130833 /* FeedReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03CC11ED2652F6B900130833 /* FeedReader.swift */; }; 03CC11F02652F70800130833 /* CCTrayFeedReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03CC11EF2652F70800130833 /* CCTrayFeedReader.swift */; }; 03CC11F2265467C200130833 /* CCTrayResponseParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03CC11F1265467C200130833 /* CCTrayResponseParser.swift */; }; @@ -93,6 +92,9 @@ 2FA28718B9A6BD8E1C32FF55 /* CCTrayResponseParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA28075764358E9D929CECD /* CCTrayResponseParserTests.swift */; }; 2FA28FBCC0398D63EF2D2C16 /* NSImageExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA28CB152CE8C0CFD6EE3A8 /* NSImageExtensionTests.swift */; }; 3C4DEDA22B49AB7A00B85A8C /* NSWorkspaceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4DEDA12B49AB7A00B85A8C /* NSWorkspaceExtension.swift */; }; + 3C95D3512BAC601C007AED1E /* ServerMonitorIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C95D3502BAC601C007AED1E /* ServerMonitorIntegrationTests.swift */; }; + 3C95D3582BAC651A007AED1E /* Hummingbird in Frameworks */ = {isa = PBXBuildFile; productRef = 3C95D3572BAC651A007AED1E /* Hummingbird */; }; + 3C95D35A2BAC651A007AED1E /* HummingbirdAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 3C95D3592BAC651A007AED1E /* HummingbirdAuth */; }; 3C9E0E532B9F143A00327CB9 /* NSApplicationExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9E0E522B9F143A00327CB9 /* NSApplicationExtension.swift */; }; 3CB911D52B7142A0009DF781 /* URLSessionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB911D42B7142A0009DF781 /* URLSessionExtension.swift */; }; 3CB911D72B78E891009DF781 /* URLRequestExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB911D62B78E891009DF781 /* URLRequestExtension.swift */; }; @@ -114,6 +116,13 @@ remoteGlobalIDString = 03BD7E842598E578000F9495; remoteInfo = CCMenu; }; + 3C95D3522BAC601C007AED1E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 03BD7E7D2598E578000F9495 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 03BD7E842598E578000F9495; + remoteInfo = CCMenu; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -176,7 +185,6 @@ 03BD7EDA2598ED9B000F9495 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; 03BD7EF9259A180C000F9495 /* NSImageExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSImageExtension.swift; sourceTree = ""; }; 03CC11E92652F49100130833 /* ServerMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerMonitor.swift; sourceTree = ""; }; - 03CC11EB2652F58B00130833 /* ServerMonitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerMonitorTests.swift; sourceTree = ""; }; 03CC11ED2652F6B900130833 /* FeedReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedReader.swift; sourceTree = ""; }; 03CC11EF2652F70800130833 /* CCTrayFeedReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCTrayFeedReader.swift; sourceTree = ""; }; 03CC11F1265467C200130833 /* CCTrayResponseParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCTrayResponseParser.swift; sourceTree = ""; }; @@ -207,6 +215,9 @@ 2FA2833D541ABE8B0D2E7615 /* GitHubResponseParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitHubResponseParserTests.swift; sourceTree = ""; }; 2FA28CB152CE8C0CFD6EE3A8 /* NSImageExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSImageExtensionTests.swift; sourceTree = ""; }; 3C4DEDA12B49AB7A00B85A8C /* NSWorkspaceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWorkspaceExtension.swift; sourceTree = ""; }; + 3C95D34E2BAC601C007AED1E /* CCMenuIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CCMenuIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C95D3502BAC601C007AED1E /* ServerMonitorIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerMonitorIntegrationTests.swift; sourceTree = ""; }; + 3C95D3612BAC6E8B007AED1E /* CCMenuTesting.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CCMenuTesting.entitlements; sourceTree = ""; }; 3C9E0E522B9F143A00327CB9 /* NSApplicationExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSApplicationExtension.swift; sourceTree = ""; }; 3CB911D42B7142A0009DF781 /* URLSessionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionExtension.swift; sourceTree = ""; }; 3CB911D62B78E891009DF781 /* URLRequestExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestExtension.swift; sourceTree = ""; }; @@ -238,6 +249,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3C95D34B2BAC601C007AED1E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C95D3582BAC651A007AED1E /* Hummingbird in Frameworks */, + 3C95D35A2BAC651A007AED1E /* HummingbirdAuth in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -311,6 +331,7 @@ 0336DBA929846EB800E5811C /* README.md */, 03BD7E872598E579000F9495 /* CCMenu */, 03BD7E9D2598E57A000F9495 /* CCMenuTests */, + 3C95D34F2BAC601C007AED1E /* CCMenuIntegrationTests */, 03BD7EA82598E57A000F9495 /* CCMenuUITests */, 03BD7E862598E578000F9495 /* Products */, 032205182B8EA73100205DC6 /* Frameworks */, @@ -323,6 +344,7 @@ 03BD7E852598E578000F9495 /* CCMenu.app */, 03BD7E9A2598E57A000F9495 /* CCMenuTests.xctest */, 03BD7EA52598E57A000F9495 /* CCMenuUITests.xctest */, + 3C95D34E2BAC601C007AED1E /* CCMenuIntegrationTests.xctest */, ); name = Products; sourceTree = ""; @@ -355,7 +377,6 @@ 03B021242A5D9F9D00B889BE /* MenuExtraModelTests.swift */, 03B1D75E2A6079CD007BCB8A /* MenuItemModelTests.swift */, 03B1D7622A6085F1007BCB8A /* PipelineRowModelTests.swift */, - 03CC11EB2652F58B00130833 /* ServerMonitorTests.swift */, 03F9B899297D930A00FA866E /* CCTrayFeedReaderTests.swift */, 2FA28075764358E9D929CECD /* CCTrayResponseParserTests.swift */, 2FA2833D541ABE8B0D2E7615 /* GitHubResponseParserTests.swift */, @@ -481,6 +502,7 @@ children = ( 03BD7E942598E57A000F9495 /* Info.plist */, 03BD7E952598E57A000F9495 /* CCMenu.entitlements */, + 3C95D3612BAC6E8B007AED1E /* CCMenuTesting.entitlements */, 03BD7EDA2598ED9B000F9495 /* Credits.rtf */, ); path = Resources; @@ -501,6 +523,14 @@ path = "Server Monitor"; sourceTree = ""; }; + 3C95D34F2BAC601C007AED1E /* CCMenuIntegrationTests */ = { + isa = PBXGroup; + children = ( + 3C95D3502BAC601C007AED1E /* ServerMonitorIntegrationTests.swift */, + ); + path = CCMenuIntegrationTests; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -565,13 +595,35 @@ productReference = 03BD7EA52598E57A000F9495 /* CCMenuUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; + 3C95D34D2BAC601C007AED1E /* CCMenuIntegrationTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3C95D3562BAC601C007AED1E /* Build configuration list for PBXNativeTarget "CCMenuIntegrationTests" */; + buildPhases = ( + 3C95D34A2BAC601C007AED1E /* Sources */, + 3C95D34B2BAC601C007AED1E /* Frameworks */, + 3C95D34C2BAC601C007AED1E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3C95D3532BAC601C007AED1E /* PBXTargetDependency */, + ); + name = CCMenuIntegrationTests; + packageProductDependencies = ( + 3C95D3572BAC651A007AED1E /* Hummingbird */, + 3C95D3592BAC651A007AED1E /* HummingbirdAuth */, + ); + productName = CCMenuIntegrationTests; + productReference = 3C95D34E2BAC601C007AED1E /* CCMenuIntegrationTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 03BD7E7D2598E578000F9495 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1230; + LastSwiftUpdateCheck = 1530; LastUpgradeCheck = 1420; TargetAttributes = { 03BD7E842598E578000F9495 = { @@ -585,6 +637,10 @@ CreatedOnToolsVersion = 12.3; TestTargetID = 03BD7E842598E578000F9495; }; + 3C95D34D2BAC601C007AED1E = { + CreatedOnToolsVersion = 15.3; + TestTargetID = 03BD7E842598E578000F9495; + }; }; }; buildConfigurationList = 03BD7E802598E578000F9495 /* Build configuration list for PBXProject "CCMenu" */; @@ -607,6 +663,7 @@ targets = ( 03BD7E842598E578000F9495 /* CCMenu */, 03BD7E992598E57A000F9495 /* CCMenuTests */, + 3C95D34D2BAC601C007AED1E /* CCMenuIntegrationTests */, 03BD7EA42598E57A000F9495 /* CCMenuUITests */, ); }; @@ -648,6 +705,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3C95D34C2BAC601C007AED1E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -738,7 +802,6 @@ buildActionMask = 2147483647; files = ( 03D4BB012659A1120023F4CB /* PipelineTests.swift in Sources */, - 03CC11EC2652F58B00130833 /* ServerMonitorTests.swift in Sources */, 037AB21C297B4D5F00C33589 /* PipelineModelTests.swift in Sources */, 2FA28FBCC0398D63EF2D2C16 /* NSImageExtensionTests.swift in Sources */, 03B021252A5D9F9D00B889BE /* MenuExtraModelTests.swift in Sources */, @@ -766,6 +829,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3C95D34A2BAC601C007AED1E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C95D3512BAC601C007AED1E /* ServerMonitorIntegrationTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -779,6 +850,11 @@ target = 03BD7E842598E578000F9495 /* CCMenu */; targetProxy = 03BD7EA62598E57A000F9495 /* PBXContainerItemProxy */; }; + 3C95D3532BAC601C007AED1E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 03BD7E842598E578000F9495 /* CCMenu */; + targetProxy = 3C95D3522BAC601C007AED1E /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -1055,6 +1131,241 @@ }; name = Release; }; + 3C95D3542BAC601C007AED1E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ccmenu.CCMenuIntegrationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCMenu.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CCMenu"; + }; + name = Debug; + }; + 3C95D3552BAC601C007AED1E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ccmenu.CCMenuIntegrationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCMenu.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CCMenu"; + }; + name = Release; + }; + 3C95D35C2BAC6DE3007AED1E /* Testing */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + UNIT_TEST_BUILD = true; + }; + name = Testing; + }; + 3C95D35D2BAC6DE3007AED1E /* Testing */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = CCMenu/Resources/CCMenuTesting.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_ASSET_PATHS = "\"CCMenu/Preview Content\""; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = CCMenu/Resources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.sourceforge.cruisecontrol.CCMenu; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Testing; + }; + 3C95D35E2BAC6DE3007AED1E /* Testing */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = CCMenuTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.ccmenu.CCMenuTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCMenu.app/Contents/MacOS/CCMenu"; + }; + name = Testing; + }; + 3C95D35F2BAC6DE3007AED1E /* Testing */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.ccmenu.CCMenuIntegrationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCMenu.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/CCMenu"; + }; + name = Testing; + }; + 3C95D3602BAC6DE3007AED1E /* Testing */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_ENTITLEMENTS = CCMenuUITests/CCMenuUITests.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = CCMenuUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.ccmenu.CCMenuUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = CCMenu; + }; + name = Testing; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1062,6 +1373,7 @@ isa = XCConfigurationList; buildConfigurations = ( 03BD7EAC2598E57A000F9495 /* Debug */, + 3C95D35C2BAC6DE3007AED1E /* Testing */, 03BD7EAD2598E57A000F9495 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1071,6 +1383,7 @@ isa = XCConfigurationList; buildConfigurations = ( 03BD7EAF2598E57A000F9495 /* Debug */, + 3C95D35D2BAC6DE3007AED1E /* Testing */, 03BD7EB02598E57A000F9495 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1080,6 +1393,7 @@ isa = XCConfigurationList; buildConfigurations = ( 03BD7EB22598E57A000F9495 /* Debug */, + 3C95D35E2BAC6DE3007AED1E /* Testing */, 03BD7EB32598E57A000F9495 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1089,11 +1403,22 @@ isa = XCConfigurationList; buildConfigurations = ( 03BD7EB52598E57A000F9495 /* Debug */, + 3C95D3602BAC6DE3007AED1E /* Testing */, 03BD7EB62598E57A000F9495 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 3C95D3562BAC601C007AED1E /* Build configuration list for PBXNativeTarget "CCMenuIntegrationTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3C95D3542BAC601C007AED1E /* Debug */, + 3C95D35F2BAC6DE3007AED1E /* Testing */, + 3C95D3552BAC601C007AED1E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ @@ -1139,6 +1464,16 @@ package = 032205372B9D29DB00205DC6 /* XCRemoteSwiftPackageReference "SettingsAccess" */; productName = SettingsAccess; }; + 3C95D3572BAC651A007AED1E /* Hummingbird */ = { + isa = XCSwiftPackageProductDependency; + package = 032205152B8EA60900205DC6 /* XCRemoteSwiftPackageReference "hummingbird" */; + productName = Hummingbird; + }; + 3C95D3592BAC651A007AED1E /* HummingbirdAuth */ = { + isa = XCSwiftPackageProductDependency; + package = 0322052C2B96769800205DC6 /* XCRemoteSwiftPackageReference "hummingbird-auth" */; + productName = HummingbirdAuth; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 03BD7E7D2598E578000F9495 /* Project object */; diff --git a/CCMenu.xcodeproj/xcshareddata/xcschemes/CCMenu.xcscheme b/CCMenu.xcodeproj/xcshareddata/xcschemes/CCMenu.xcscheme index 6f27afb..3b4e0a7 100644 --- a/CCMenu.xcodeproj/xcshareddata/xcschemes/CCMenu.xcscheme +++ b/CCMenu.xcodeproj/xcshareddata/xcschemes/CCMenu.xcscheme @@ -23,13 +23,17 @@ + + @@ -44,6 +48,16 @@ ReferencedContainer = "container:CCMenu.xcodeproj"> + + + + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.disable-library-validation + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/CCMenu/Source/Server Monitor/GitHubFeedReader.swift b/CCMenu/Source/Server Monitor/GitHubFeedReader.swift index 213b621..fc2c76c 100644 --- a/CCMenu/Source/Server Monitor/GitHubFeedReader.swift +++ b/CCMenu/Source/Server Monitor/GitHubFeedReader.swift @@ -39,12 +39,6 @@ class GitHubFeedReader { public func updatePipelineStatus() async { do { let token = try Keychain().getToken(forService: "GitHub") - if let pauseUntil = pipeline.feed.pauseUntil { - guard Date().timeIntervalSince1970 >= Double(pauseUntil) else { - return - } - pipeline.feed.clearPauseUntil() - } guard let request = GitHubAPI.requestForFeed(feed: pipeline.feed, token: token) else { throw GithHubFeedReaderError.invalidURLError } diff --git a/CCMenu/Source/Server Monitor/ServerMonitor.swift b/CCMenu/Source/Server Monitor/ServerMonitor.swift index 2512bca..75b4376 100644 --- a/CCMenu/Source/Server Monitor/ServerMonitor.swift +++ b/CCMenu/Source/Server Monitor/ServerMonitor.swift @@ -51,7 +51,7 @@ class ServerMonitor { newPipelines.forEach({ p in Task { await updateStatus(pipeline: p) } }) } - private func updateStatus(pipelines: [Pipeline]) async { + func updateStatus(pipelines: [Pipeline]) async { if Date().timeIntervalSince(lastPoll).rounded() < pollInterval { return } @@ -63,10 +63,15 @@ class ServerMonitor { private func updateStatus(pipeline p: Pipeline) async { if !networkMonitor.isConnected && pipelineIsRemote(p) && pipelineHasSomeStatus(p) { - debugPrint("skipping/down \(p.feed.url)") return } - debugPrint("checking \(p.feed.url)") + var p = p + if let pauseUntil = p.feed.pauseUntil { + if Date().timeIntervalSince1970 <= Double(pauseUntil) { + return + } + p.feed.clearPauseUntil() + } // TODO: Multiple request will pile up if requests take longer than poll intervall switch(p.feed.type) { case .cctray: diff --git a/CCMenuIntegrationTests/ServerMonitorIntegrationTests.swift b/CCMenuIntegrationTests/ServerMonitorIntegrationTests.swift new file mode 100644 index 0000000..d78c354 --- /dev/null +++ b/CCMenuIntegrationTests/ServerMonitorIntegrationTests.swift @@ -0,0 +1,101 @@ +/* + * Copyright (c) Erik Doernenburg and contributors + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use these files except in compliance with the License. + */ + +import XCTest +import Hummingbird +@testable import CCMenu + +final class ServerMonitorIntegrationTests: XCTestCase { + + var webapp: HBApplication! + + override func setUpWithError() throws { + webapp = HBApplication(configuration: .init(address: .hostname("localhost", port: 8086), logLevel: .error)) + try webapp.start() + } + + override func tearDownWithError() throws { + webapp.stop() + } + + + func testDoesntPollWhenPipelineIsPaused() async throws { + var requestCounter = 0 + webapp.router.get("/runs", options: .editResponse) { r -> String in + requestCounter += 1 + r.response.status = .forbidden + return "{ }" + } + + let model = PipelineModel() + var pipeline = Pipeline(name: "CCMenu2", feed: Pipeline.Feed(type: .github, url: "http://localhost:8086/runs", name: nil)) + pipeline.feed.pauseUntil = Int(Date(timeIntervalSinceNow: +600).timeIntervalSince1970) + model.add(pipeline: pipeline) + + let monitor = await ServerMonitor(model: model) + await monitor.updateStatus(pipelines: model.pipelines) + + XCTAssertEqual(0, requestCounter) + } + + func testPollsAndClearsPausedIfPausedUntilIsInThePast() async throws { + webapp.router.get("/cctray.xml") { _ in """ + + + + """} + + let model = PipelineModel() + var pipeline = Pipeline(name: "connectfour", feed: Pipeline.Feed(type: .cctray, url: "http://localhost:8086/cctray.xml", name: "connectfour")) + pipeline.feed.pauseUntil = Int(Date(timeIntervalSinceNow: -5).timeIntervalSince1970) + model.add(pipeline: pipeline) + + let monitor = await ServerMonitor(model: model) + await monitor.updateStatus(pipelines: model.pipelines) + + XCTAssertNil(model.pipelines.first?.feed.pauseUntil) + XCTAssertEqual("build.888", model.pipelines.first?.status.lastBuild?.label) + } + + func testShowsErrorWhenConnectionFails() async throws { + webapp.stop() + + let model = PipelineModel() + model.add(pipeline: Pipeline(name: "connectfour", feed: Pipeline.Feed(type: .cctray, url: "http://localhost:8086/cctray.xml", name: "connectfour"))) + + let monitor = await ServerMonitor(model: model) + await monitor.updateStatus(pipelines: model.pipelines) + + XCTAssertEqual("Could not connect to the server.", model.pipelines.first?.connectionError) + } + + func testShowsErrorForHTTPError() async throws { + let model = PipelineModel() + model.add(pipeline: Pipeline(name: "connectfour", feed: Pipeline.Feed(type: .cctray, url: "http://localhost:8086/cctray.xml", name: "connectfour"))) + + let monitor = await ServerMonitor(model: model) + await monitor.updateStatus(pipelines: model.pipelines) + + XCTAssertEqual("The server responded: not found", model.pipelines.first?.connectionError) + } + + func testShowsErrorWhenFeedDoesntContainProject() async throws { + webapp.router.get("/cctray.xml") { _ in """ + + + + """} + + let model = PipelineModel() + model.add(pipeline: Pipeline(name: "connectfour", feed: Pipeline.Feed(type: .cctray, url: "http://localhost:8086/cctray.xml", name: "connectfour"))) + + let monitor = await ServerMonitor(model: model) + await monitor.updateStatus(pipelines: model.pipelines) + + XCTAssertEqual("The server did not provide a status for this pipeline.", model.pipelines.first?.connectionError) + } + +} diff --git a/CCMenuTests/ServerMonitorTests.swift b/CCMenuTests/ServerMonitorTests.swift deleted file mode 100644 index b948be8..0000000 --- a/CCMenuTests/ServerMonitorTests.swift +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Erik Doernenburg and contributors - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use these files except in compliance with the License. - */ - -import XCTest -@testable import CCMenu - -class ServerMonitorTests: XCTestCase { - -// func testCreatesConnectionForPipeline() throws { -// let model = ViewModel() -// let p0 = Pipeline(name: "connectfour", feedUrl: "http://test/cctray.xml") -// model.pipelines.append(p0) -// -// let monitor = ServerMonitor(model: model) -// monitor.createReaders() -// -// XCTAssertEqual(1, monitor.readerList.count) -// } - -} - diff --git a/CCMenuUITests/CCTrayTests.swift b/CCMenuUITests/CCTrayTests.swift index d200b20..53faf33 100644 --- a/CCMenuUITests/CCTrayTests.swift +++ b/CCMenuUITests/CCTrayTests.swift @@ -44,35 +44,6 @@ class CCTrayTests: XCTestCase { waitForExpectations(timeout: 2) } - func testShowsErrorWhenFeedDoesntContainProject() throws { - webapp.router.get("/cctray.xml") { _ in """ - - - - """} - - let app = TestHelper.launchApp(pipelines: "CCTrayPipeline.json", pauseMonitor: false) - let window = app.windows["Pipelines"] - - // Find the status description field (there's only one because there's only one pipeline), then - // wait for the update to the status text displaying the error message - let descriptionText = window.tables.staticTexts["Status description"] - expectation(for: NSPredicate(format: "value CONTAINS 'The server did not provide a status'"), evaluatedWith: descriptionText) - waitForExpectations(timeout: 5) - } - - func testShowsErrorForHTTPError() throws { - let app = TestHelper.launchApp(pipelines: "CCTrayPipeline.json", pauseMonitor: false) - let window = app.windows["Pipelines"] - - // Find the status description field (there's only one because there's only one pipeline), then - // wait for the error meesage from the embedded server, which is not found because we didn't - // register any routes - let descriptionText = window.tables.staticTexts["Status description"] - expectation(for: NSPredicate(format: "value CONTAINS 'The server responded: not found'"), evaluatedWith: descriptionText) - waitForExpectations(timeout: 5) - } - func testAddsPipeline() throws { webapp.router.get("/cctray.xml") { _ in """