diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5acfaf91..f1f6f27b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,6 @@ jobs: uses: actions/checkout@v3 - name: xcodegen uses: xavierLowmiller/xcodegen-action@1.1.2 - - name: Build + - name: Build and run tests run: | ./ci-build.sh diff --git a/AeroSpace.xcodeproj/project.pbxproj b/AeroSpace.xcodeproj/project.pbxproj index 78da4809..153b2b19 100644 --- a/AeroSpace.xcodeproj/project.pbxproj +++ b/AeroSpace.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 6317AB471F4C4F5D66A25784 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EEDBFFCA7A77D96B18FB0732 /* Assets.xcassets */; }; 64A058E536F1EEF7F01043AF /* TOMLKit in Frameworks */ = {isa = PBXBuildFile; productRef = EC8E4F2CA4FF8884F9F59975 /* TOMLKit */; }; 66E6CDA75DDD5E4B9647EDE2 /* AeroSpaceApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E81623E8954701269A22322 /* AeroSpaceApp.swift */; }; + 6715CC184E718828173DFBD5 /* ConfigTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12EA50A972BA714F2BA3BBC1 /* ConfigTest.swift */; }; 6820E6846AE51B6988B6F673 /* utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD02433B4415EEB163074CE5 /* utils.swift */; }; 6E4E235FDA41307B19F16182 /* ModeCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CD3C2A0E86CDB9DF312AB /* ModeCommand.swift */; }; 783B0B965BA45D7A2943F7BF /* TilingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E05FB0C7158C8B6DECBD603 /* TilingContainer.swift */; }; @@ -42,13 +43,25 @@ B1E2002BB8F70F2555AAA82D /* TreeNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D295CA45172ADBDB1E4DF708 /* TreeNode.swift */; }; B3702BB393A9B03CCAE4C60E /* refresh.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526B113159987FA43EA41120 /* refresh.swift */; }; E2FD8E2B2D2BE6B88BF8E8AD /* accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE605CF46DE6377C69B9D49D /* accessibility.swift */; }; + F74FC5ECBCE9C8A6D09AE9F5 /* util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7910D7B9C0A232187CCA1F10 /* util.swift */; }; F982DB924450BBBB4FDF4C2C /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD90FB41FD41602120F67FF5 /* Command.swift */; }; FC35D6D0A678CC802972C6FE /* ReloadConfigCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF3C9038C846369FDD71D1D2 /* ReloadConfigCommand.swift */; }; FD4386BC632BAA6A4105FFD8 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9752080BBA547C2A0EF076F0 /* Config.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + B514A502AE8B3770CB8BEA61 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0B585B3093DA0FC12E7983E2 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B00BE37A79171B0EE995EB83; + remoteInfo = AeroSpace; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 09685297933511208058F7CF /* AeroSpace.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AeroSpace.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 12EA50A972BA714F2BA3BBC1 /* ConfigTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigTest.swift; sourceTree = ""; }; 1A2B673C67B00DBFCC27FFE7 /* LayoutCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutCommand.swift; sourceTree = ""; }; 1C0D40CBD65704BA9595C2FA /* keysMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = keysMap.swift; sourceTree = ""; }; 1E81623E8954701269A22322 /* AeroSpaceApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AeroSpaceApp.swift; sourceTree = ""; }; @@ -64,9 +77,11 @@ 4B0CD3C2A0E86CDB9DF312AB /* ModeCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModeCommand.swift; sourceTree = ""; }; 51CE37C1B8D858C81A396F40 /* CollectionEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionEx.swift; sourceTree = ""; }; 526B113159987FA43EA41120 /* refresh.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = refresh.swift; sourceTree = ""; }; + 5274C575044C2A7123C57584 /* AeroSpace-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "AeroSpace-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 55E2A2BBD8A32FFCD6A88BC7 /* BashCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BashCommand.swift; sourceTree = ""; }; 67DBAF4ECF8A0B931FC34EAD /* parseConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = parseConfig.swift; sourceTree = ""; }; 6935AF0A2DB3D186D1C6218F /* NSWorkspaceEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWorkspaceEx.swift; sourceTree = ""; }; + 7910D7B9C0A232187CCA1F10 /* util.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = util.swift; sourceTree = ""; }; 7E6F3930E3BF5D8196A20E9B /* axObservers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = axObservers.swift; sourceTree = ""; }; 883D7F7F87FBE7D0BDE4E87F /* ArrayEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayEx.swift; sourceTree = ""; }; 8B7A2DF0D1F72B80B1F04240 /* BundleEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleEx.swift; sourceTree = ""; }; @@ -126,6 +141,7 @@ children = ( 0E0109AE5F7881520B0D2384 /* config-examples */, 8338180CE208CBDCD6D8E911 /* src */, + A6E1E25AB6F33B13B0633B9C /* test */, 62BEA6F49E6648E2EE3C208F /* Products */, ); sourceTree = ""; @@ -143,6 +159,7 @@ 62BEA6F49E6648E2EE3C208F /* Products */ = { isa = PBXGroup; children = ( + 5274C575044C2A7123C57584 /* AeroSpace-Tests.xctest */, 09685297933511208058F7CF /* AeroSpace.app */, ); name = Products; @@ -178,6 +195,15 @@ path = axWrappers; sourceTree = ""; }; + A6E1E25AB6F33B13B0633B9C /* test */ = { + isa = PBXGroup; + children = ( + 12EA50A972BA714F2BA3BBC1 /* ConfigTest.swift */, + 7910D7B9C0A232187CCA1F10 /* util.swift */, + ); + path = test; + sourceTree = ""; + }; A711A25EEC57098295B90C17 /* command */ = { isa = PBXGroup; children = ( @@ -235,6 +261,22 @@ productReference = 09685297933511208058F7CF /* AeroSpace.app */; productType = "com.apple.product-type.application"; }; + D2B85A91A03DA984483CF473 /* AeroSpace-Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D7CB5528090130BA2AF93D7A /* Build configuration list for PBXNativeTarget "AeroSpace-Tests" */; + buildPhases = ( + 101761F785765CD965E9741C /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + A6E9756DC2D01D6E286DFADF /* PBXTargetDependency */, + ); + name = "AeroSpace-Tests"; + productName = "AeroSpace-Tests"; + productReference = 5274C575044C2A7123C57584 /* AeroSpace-Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -266,6 +308,7 @@ projectRoot = ""; targets = ( B00BE37A79171B0EE995EB83 /* AeroSpace */, + D2B85A91A03DA984483CF473 /* AeroSpace-Tests */, ); }; /* End PBXProject section */ @@ -283,6 +326,15 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 101761F785765CD965E9741C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6715CC184E718828173DFBD5 /* ConfigTest.swift in Sources */, + F74FC5ECBCE9C8A6D09AE9F5 /* util.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D7A18303C03F2CB26F7BB54B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -326,6 +378,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + A6E9756DC2D01D6E286DFADF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B00BE37A79171B0EE995EB83 /* AeroSpace */; + targetProxy = B514A502AE8B3770CB8BEA61 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 175127AAF914899705FABF12 /* Debug */ = { isa = XCBuildConfiguration; @@ -468,6 +528,38 @@ }; name = Release; }; + B3F7FD8336104A3B49E648F4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + SDKROOT = macosx; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AeroSpace-Debug.app/Contents/MacOS/AeroSpace-Debug"; + }; + name = Release; + }; + CBE2FDFF787AFE0FB33E335B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + SDKROOT = macosx; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AeroSpace-Debug.app/Contents/MacOS/AeroSpace-Debug"; + }; + name = Debug; + }; D1D1A9E07F0AB40E14CAC0F6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -516,6 +608,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + D7CB5528090130BA2AF93D7A /* Build configuration list for PBXNativeTarget "AeroSpace-Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CBE2FDFF787AFE0FB33E335B /* Debug */, + B3F7FD8336104A3B49E648F4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ diff --git a/ci-build.sh b/ci-build.sh index 9658d680..a6860fcd 100755 --- a/ci-build.sh +++ b/ci-build.sh @@ -13,3 +13,4 @@ if [ ! -z "$(git status --porcelain)" ]; then git status exit 1 fi +./run-tests.sh diff --git a/config-examples/i3-like-config-example.toml b/config-examples/i3-like-config-example.toml index 39850f87..a7898ab7 100644 --- a/config-examples/i3-like-config-example.toml +++ b/config-examples/i3-like-config-example.toml @@ -12,21 +12,24 @@ alt-j = 'focus down' alt-k = 'focus up' alt-l = 'focus right' -alt-shift-h = 'move_through left' -alt-shift-j = 'move_through down' -alt-shift-k = 'move_through up' -alt-shift-l = 'move_through right' +#todo support parsing +#alt-shift-h = 'move_through left' +#alt-shift-j = 'move_through down' +#alt-shift-k = 'move_through up' +#alt-shift-l = 'move_through right' # alt-h = 'split h' # todo support split command? # alt-v = 'split v' # todo support split command? # alt-f = 'fullscreen' # todo support fullscreen command? -alt-s = 'layout v_accordion' # 'layout stacking' in i3 -alt-w = 'layout h_accordion' # 'layout tabbed' in i3 -alt-e = 'layout h_list v_list' # 'layout toggle list' in i3 +# todo support layout parsing +#alt-s = 'layout v_accordion' # 'layout stacking' in i3 +#alt-w = 'layout h_accordion' # 'layout tabbed' in i3 +#alt-e = 'layout h_list v_list' # 'layout toggle list' in i3 -alt-shift-space = 'layout floating tiling' # 'floating toggle' in i3 +#todo support parsing +#alt-shift-space = 'layout floating tiling' # 'floating toggle' in i3 alt-space = 'focus toggle_tiling_floating' alt-a = 'focus parent' @@ -42,26 +45,28 @@ alt-8 = 'workspace 8' alt-9 = 'workspace 9' alt-0 = 'workspace 10' -alt-shift-1 = 'move container to workspace 1' -alt-shift-2 = 'move container to workspace 2' -alt-shift-3 = 'move container to workspace 3' -alt-shift-4 = 'move container to workspace 4' -alt-shift-5 = 'move container to workspace 5' -alt-shift-6 = 'move container to workspace 6' -alt-shift-7 = 'move container to workspace 7' -alt-shift-8 = 'move container to workspace 8' -alt-shift-9 = 'move container to workspace 9' -alt-shift-0 = 'move container to workspace 10' +#todo support parsing +#alt-shift-1 = 'move container to workspace 1' +#alt-shift-2 = 'move container to workspace 2' +#alt-shift-3 = 'move container to workspace 3' +#alt-shift-4 = 'move container to workspace 4' +#alt-shift-5 = 'move container to workspace 5' +#alt-shift-6 = 'move container to workspace 6' +#alt-shift-7 = 'move container to workspace 7' +#alt-shift-8 = 'move container to workspace 8' +#alt-shift-9 = 'move container to workspace 9' +#alt-shift-0 = 'move container to workspace 10' alt-shift-c = 'reload_config' alt-r = 'mode resize' -[mode.resize.binding] -# todo does it work? -h = 'resize shrink width 10' -j = 'resize grow height 10' -k = 'resize shrink height 10' -l = 'resize grow width 10' -enter = 'mode main' -esc = 'mode esc' +#todo support parsing +#[mode.resize.binding] +## todo does it work? +#h = 'resize shrink width 10' +#j = 'resize grow height 10' +#k = 'resize shrink height 10' +#l = 'resize grow width 10' +#enter = 'mode main' +#esc = 'mode esc' diff --git a/project.yml b/project.yml index 011c8d76..33550ebe 100644 --- a/project.yml +++ b/project.yml @@ -44,3 +44,14 @@ targets: properties: # Accessibility API doesn't work in sandboxed app com.apple.security.app-sandbox: false + AeroSpace-Tests: + type: bundle.unit-test + platform: macOS + sources: [test] + dependencies: + - target: AeroSpace + settings: + base: + # SWIFT_VERSION: 5.8 + TEST_HOST: "$(BUILT_PRODUCTS_DIR)/AeroSpace-Debug.app/Contents/MacOS/AeroSpace-Debug" + GENERATE_INFOPLIST_FILE: YES diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 00000000..e4123bbd --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e # Exit if one of commands exit with non-zero exit code +set -u # Treat unset variables and parameters other than the special parameters ‘@’ or ‘*’ as an error +set -o pipefail # Any command failed in the pipe fails the whole pipe +# set -x # Print shell commands as they are executed (or you can try -v which is less verbose) + +cd "$(dirname "$0")" +xcodebuild -scheme AeroSpace_Tests test diff --git a/test/ConfigTest.swift b/test/ConfigTest.swift new file mode 100644 index 00000000..872de0f6 --- /dev/null +++ b/test/ConfigTest.swift @@ -0,0 +1,16 @@ +// +// macos_window_manager_swiftTests.swift +// macos-window-manager-swiftTests +// +// Created by Nikita Bobko on 2023-05-20. +// + +import XCTest +@testable import AeroSpace_Debug + +final class ConfigTest: XCTestCase { + func testParseI3Config() throws { + let toml = try! String(contentsOf: projectRoot.appending(component: "config-examples/i3-like-config-example.toml")) + let _ = parseConfig(toml) + } +} diff --git a/test/util.swift b/test/util.swift new file mode 100644 index 00000000..d4c696de --- /dev/null +++ b/test/util.swift @@ -0,0 +1,3 @@ +import Foundation + +let projectRoot: URL = URL(filePath: #file).appending(component: "../..").standardized diff --git a/tests/macos_window_manager_swiftTests.swift b/tests/macos_window_manager_swiftTests.swift deleted file mode 100644 index 7fb525ca..00000000 --- a/tests/macos_window_manager_swiftTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// macos_window_manager_swiftTests.swift -// macos-window-manager-swiftTests -// -// Created by Nikita Bobko on 2023-05-20. -// - -import XCTest -@testable import AeroSpace - -final class macos_window_manager_swiftTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -}