diff --git a/app/xcode/App/VCam.xcodeproj/project.pbxproj b/app/xcode/App/VCam.xcodeproj/project.pbxproj index ae5ca92..7880aa4 100644 --- a/app/xcode/App/VCam.xcodeproj/project.pbxproj +++ b/app/xcode/App/VCam.xcodeproj/project.pbxproj @@ -13,10 +13,12 @@ 0612386D2ADE9A8400B67618 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0612386C2ADE9A8400B67618 /* Preview Assets.xcassets */; }; 061238752ADE9C6D00B67618 /* xcode in Resources */ = {isa = PBXBuildFile; fileRef = 061238742ADE9C6D00B67618 /* xcode */; }; 061238782ADE9CEE00B67618 /* VCam in Frameworks */ = {isa = PBXBuildFile; productRef = 061238772ADE9CEE00B67618 /* VCam */; }; + 06A72E8B2AE4305D000D0B25 /* XCUIApplication+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A72E8A2AE4305D000D0B25 /* XCUIApplication+.swift */; }; + 06A72E8D2AE4359E000D0B25 /* VCam in Frameworks */ = {isa = PBXBuildFile; productRef = 06A72E8C2AE4359E000D0B25 /* VCam */; }; + 06A72E8F2AE45073000D0B25 /* XCUIElementQuery+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06A72E8E2AE45073000D0B25 /* XCUIElementQuery+.swift */; }; 06EC61182ADEE7A900D2A5C9 /* VCamStub in Frameworks */ = {isa = PBXBuildFile; productRef = 06EC61172ADEE7A900D2A5C9 /* VCamStub */; }; 06EC61202AE016C300D2A5C9 /* VCamUIPreviewUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06EC611F2AE016C300D2A5C9 /* VCamUIPreviewUITests.swift */; }; 06EC61222AE016C300D2A5C9 /* LaunchScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06EC61212AE016C300D2A5C9 /* LaunchScreenshotTests.swift */; }; - 06EC61292AE0296600D2A5C9 /* VCamLocalization in Frameworks */ = {isa = PBXBuildFile; productRef = 06EC61282AE0296600D2A5C9 /* VCamLocalization */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -37,6 +39,8 @@ 0612386C2ADE9A8400B67618 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 0612386E2ADE9A8400B67618 /* VCamUIPreview.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = VCamUIPreview.entitlements; sourceTree = ""; }; 061238742ADE9C6D00B67618 /* xcode */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = xcode; path = ..; sourceTree = ""; }; + 06A72E8A2AE4305D000D0B25 /* XCUIApplication+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIApplication+.swift"; sourceTree = ""; }; + 06A72E8E2AE45073000D0B25 /* XCUIElementQuery+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElementQuery+.swift"; sourceTree = ""; }; 06EC611D2AE016C300D2A5C9 /* VCamUIPreviewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VCamUIPreviewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 06EC611F2AE016C300D2A5C9 /* VCamUIPreviewUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VCamUIPreviewUITests.swift; sourceTree = ""; }; 06EC61212AE016C300D2A5C9 /* LaunchScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchScreenshotTests.swift; sourceTree = ""; }; @@ -56,7 +60,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 06EC61292AE0296600D2A5C9 /* VCamLocalization in Frameworks */, + 06A72E8D2AE4359E000D0B25 /* VCam in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -115,6 +119,8 @@ children = ( 06EC611F2AE016C300D2A5C9 /* VCamUIPreviewUITests.swift */, 06EC61212AE016C300D2A5C9 /* LaunchScreenshotTests.swift */, + 06A72E8A2AE4305D000D0B25 /* XCUIApplication+.swift */, + 06A72E8E2AE45073000D0B25 /* XCUIElementQuery+.swift */, ); path = VCamUIPreviewUITests; sourceTree = ""; @@ -158,7 +164,7 @@ ); name = VCamUIPreviewUITests; packageProductDependencies = ( - 06EC61282AE0296600D2A5C9 /* VCamLocalization */, + 06A72E8C2AE4359E000D0B25 /* VCam */, ); productName = VCamUIPreviewUITests; productReference = 06EC611D2AE016C300D2A5C9 /* VCamUIPreviewUITests.xctest */; @@ -237,6 +243,8 @@ buildActionMask = 2147483647; files = ( 06EC61222AE016C300D2A5C9 /* LaunchScreenshotTests.swift in Sources */, + 06A72E8B2AE4305D000D0B25 /* XCUIApplication+.swift in Sources */, + 06A72E8F2AE45073000D0B25 /* XCUIElementQuery+.swift in Sources */, 06EC61202AE016C300D2A5C9 /* VCamUIPreviewUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -499,13 +507,13 @@ isa = XCSwiftPackageProductDependency; productName = VCam; }; - 06EC61172ADEE7A900D2A5C9 /* VCamStub */ = { + 06A72E8C2AE4359E000D0B25 /* VCam */ = { isa = XCSwiftPackageProductDependency; - productName = VCamStub; + productName = VCam; }; - 06EC61282AE0296600D2A5C9 /* VCamLocalization */ = { + 06EC61172ADEE7A900D2A5C9 /* VCamStub */ = { isa = XCSwiftPackageProductDependency; - productName = VCamLocalization; + productName = VCamStub; }; /* End XCSwiftPackageProductDependency section */ }; diff --git a/app/xcode/App/VCamUIPreview/VCamUIPreviewApp.swift b/app/xcode/App/VCamUIPreview/VCamUIPreviewApp.swift index 3334a99..c1e6611 100644 --- a/app/xcode/App/VCamUIPreview/VCamUIPreviewApp.swift +++ b/app/xcode/App/VCamUIPreview/VCamUIPreviewApp.swift @@ -26,6 +26,10 @@ struct VCamUIPreviewApp: App { final class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { + if ProcessInfo.processInfo.arguments.contains("UITesting") { + UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) + } + Task { await configureApp() } diff --git a/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift b/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift index 29c4037..cb4cc4b 100644 --- a/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift +++ b/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift @@ -7,11 +7,12 @@ import XCTest import VCamLocalization +import VCamUI final class LaunchScreenshotTests: XCTestCase { override class var runsForEachTargetApplicationUIConfiguration: Bool { - true + false // Light mode only } override func setUpWithError() throws { @@ -20,29 +21,59 @@ final class LaunchScreenshotTests: XCTestCase { } func testLaunch() throws { - let app = XCUIApplication() + let app = XCUIApplication.make() app.launch() - // Close the alert about the virtual camera if needed" - if app.staticTexts[L10n.installVirtualCamera.text].exists { - app.buttons["OK"].click() - app.buttons["OK"].click() + XCTContext.runActivity(named: "Launch Screen") { activity in + add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "Launch Screen") { activity in + XCTContext.runActivity(named: "\(L10n.screenEffect.text) Screen") { activity in + app.buttons.contains(label: L10n.screenEffect.text).click() + _ = app.staticTexts[L10n.startRecording.text].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } XCTContext.runActivity(named: "\(L10n.recording.text) Screen") { activity in - app.buttons[L10n.recording.text].click() + app.buttons.contains(label: L10n.recording.text).click() _ = app.staticTexts[L10n.whiteBalance.text].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(L10n.screenEffect.text) Screen") { activity in - app.buttons[L10n.screenEffect.text].click() - _ = app.staticTexts[L10n.startRecording.text].waitForExistence(timeout: 5) + XCTContext.runActivity(named: "\(L10n.settings.text) Screen") { activity in + app.buttons["btn_settings"].click() + _ = app.staticTexts[L10n.settings.text].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) + XCTAssertTrue(app.cells.firstMatch.isSelected) + + XCTContext.runActivity(named: "\(activity.name) - \(L10n.rendering.text)") { activity in + app.cells.staticTexts[L10n.rendering.text].click() + _ = app.staticTexts[L10n.renderingQuality.text].waitForExistence(timeout: 5) + add(.keepAlways(screenshot: app.screenshot(), activity: activity)) + } + + XCTContext.runActivity(named: "\(activity.name) - \(L10n.tracking.text)") { activity in + app.cells.staticTexts[L10n.tracking.text].click() + _ = app.staticTexts[L10n.fpsCamera.text].waitForExistence(timeout: 5) + add(.keepAlways(screenshot: app.screenshot(), activity: activity)) + } + + XCTContext.runActivity(named: "\(activity.name) - \(L10n.virtualCamera.text)") { activity in + app.cells.staticTexts[L10n.virtualCamera.text].click() + _ = app.staticTexts[L10n.noteEnableNewCameraExtension.text].waitForExistence(timeout: 5) + add(.keepAlways(screenshot: app.screenshot(), activity: activity)) + } + + XCTContext.runActivity(named: "\(activity.name) - \(L10n.integration.text)") { activity in + app.cells.staticTexts[L10n.integration.text].click() + _ = app.staticTexts["VCamMocap"].waitForExistence(timeout: 5) + add(.keepAlways(screenshot: app.screenshot(), activity: activity)) + } + + XCTContext.runActivity(named: "\(activity.name) - \(L10n.experiment.text)") { activity in + app.cells.staticTexts[L10n.experiment.text].click() + add(.keepAlways(screenshot: app.screenshot(), activity: activity)) + } } } } diff --git a/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift b/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift index fabf288..89c1528 100644 --- a/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift +++ b/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift @@ -19,17 +19,11 @@ final class VCamUIPreviewUITests: XCTestCase { } func testLaunchApp() throws { - let app = XCUIApplication() + let app = XCUIApplication.make() app.launch() - // Close the alert about the virtual camera if needed" - if app.staticTexts[L10n.installVirtualCamera.text].exists { - app.buttons["OK"].click() - app.buttons["OK"].click() - } - XCTContext.runActivity(named: "Check VCamUI") { _ in - XCTAssertTrue(app.buttons[L10n.main.text].exists) + XCTAssertTrue(app.buttons.contains(label: L10n.main.text).exists) } } } diff --git a/app/xcode/App/VCamUIPreviewUITests/XCUIApplication+.swift b/app/xcode/App/VCamUIPreviewUITests/XCUIApplication+.swift new file mode 100644 index 0000000..08cea43 --- /dev/null +++ b/app/xcode/App/VCamUIPreviewUITests/XCUIApplication+.swift @@ -0,0 +1,30 @@ +// +// XCUIApplication+.swift +// VCamUIPreviewUITests +// +// Created by Tatsuya Tanaka on 2023/10/22. +// + +import XCTest +import VCamData +import VCamDefaults + +extension XCUIApplication { + struct Configuration { + static let `default` = Configuration() + var previousVersion: String? = "999.9.9" // skip migration + } + + static func make(with configuration: Configuration = .default) -> XCUIApplication { + let app = XCUIApplication() + app.launchArguments += ["UITesting"] + if let value = configuration.previousVersion { + app.setUserDefaults(value: value, for: .previousVersion) + } + return app + } + + func setUserDefaults(value: String, for key: UserDefaults.Key) { + launchArguments += ["-\(key.rawValue)", value] + } +} diff --git a/app/xcode/App/VCamUIPreviewUITests/XCUIElementQuery+.swift b/app/xcode/App/VCamUIPreviewUITests/XCUIElementQuery+.swift new file mode 100644 index 0000000..0def5f3 --- /dev/null +++ b/app/xcode/App/VCamUIPreviewUITests/XCUIElementQuery+.swift @@ -0,0 +1,14 @@ +// +// XCUIElementQuery+.swift +// VCamUIPreviewUITests +// +// Created by Tatsuya Tanaka on 2023/10/22. +// + +import XCTest + +extension XCUIElementQuery { + func contains(label: String) -> XCUIElement { + containing(.init(format: "label CONTAINS '\(label)'")).element + } +} diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingExperimentView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingExperimentView.swift index 40fa049..1621d67 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingExperimentView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingExperimentView.swift @@ -8,5 +8,7 @@ import SwiftUI public enum VCamSettingExperimentView { - public static var make: () -> AnyView = { fatalError() } + public static var make: () -> AnyView = { + AnyView(EmptyView()) + } } diff --git a/app/xcode/Sources/VCamUI/VCamMenu.swift b/app/xcode/Sources/VCamUI/VCamMenu.swift index 88fe809..5800003 100644 --- a/app/xcode/Sources/VCamUI/VCamMenu.swift +++ b/app/xcode/Sources/VCamUI/VCamMenu.swift @@ -84,6 +84,7 @@ private struct MenuBottomView: View { } .buttonStyle(.plain) .disabled(recorder.isRecording) + .accessibilityIdentifier("btn_settings") } .controlSize(.small) @@ -126,6 +127,7 @@ private struct VCamMenuButtonStyle: ButtonStyle { ) .cornerRadius(6.0) .contentShape(Rectangle()) + .accessibilityAddTraits(isSelected ? [.isButton, .isSelected] : [.isButton]) } } diff --git a/app/xcode/Sources/VCamUI/VCamSystem.swift b/app/xcode/Sources/VCamUI/VCamSystem.swift index 09d8f80..b15a76d 100644 --- a/app/xcode/Sources/VCamUI/VCamSystem.swift +++ b/app/xcode/Sources/VCamUI/VCamSystem.swift @@ -37,7 +37,13 @@ public final class VCamSystem { Task { @MainActor in if !windowManager.isUnity { +#if DEBUG + if !ProcessInfo.processInfo.arguments.contains("UITesting") { + await AppUpdater.vcam.presentUpdateAlertIfAvailable() + } +#else await AppUpdater.vcam.presentUpdateAlertIfAvailable() +#endif } await Migration.migrate()