catalyst-core 0.3.0-beta.5 → 0.3.0-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +185 -71
- package/dist/errors/generateDocs.js +100 -0
- package/dist/errors/index.js +243 -0
- package/dist/errors/registry.js +483 -0
- package/dist/errors-index.json +506 -0
- package/dist/globals.d.ts +62 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.jsx +5 -8
- package/dist/logger.js +1 -1
- package/dist/native/androidProject/app/build.gradle.kts +142 -7
- package/dist/native/androidProject/app/src/main/AndroidManifest.xml +4 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +2 -2
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/BarcodeDetector.kt +3 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/CameraSessionManager.kt +3 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +43 -8
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/BridgeUtilsTest.kt +181 -1
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/CameraUtilsTest.kt +156 -236
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FileSizeRouterUtilsTest.kt +471 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FileUtilsTest.kt +222 -226
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FrameworkServerUtilsTest.kt +300 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/IntentUtilsTest.kt +244 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/MetricsMonitorTest.kt +359 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/NativeBridgeTest.kt +108 -63
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/NotificationUtilsTest.kt +329 -385
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/OfflineCacheServiceTest.kt +302 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/PerfEventBufferTest.kt +133 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/UtilsKtTest.kt +152 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/WebCacheManagerTest.kt +145 -324
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/BarcodeDetectorTest.kt +132 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/HoldControllerTest.kt +155 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/TorchControllerTest.kt +150 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/VideoStreamStateMachineTest.kt +120 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/VideoStreamStateTest.kt +62 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/ViewfinderMapperTest.kt +143 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/ZoomControllerTest.kt +421 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/design/DesignTokensTest.kt +207 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/plugins/PluginBridgeTest.kt +368 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/FridaDetectorTest.kt +193 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/SecurityCheckManagerTest.kt +260 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/SecurityCheckSchedulerTest.kt +166 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/DeviceInfoUtilsTest.kt +167 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/DownloadUtilsTest.kt +197 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/NetworkMonitorTest.kt +271 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/PushNotificationUtilsTest.kt +119 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/SafeAreaUtilsTest.kt +108 -0
- package/dist/native/androidProject/build.gradle.kts +1 -0
- package/dist/native/androidProject/gradle/libs.versions.toml +26 -0
- package/dist/native/androidProject/settings.gradle.kts +11 -8
- package/dist/native/androidSetup.js +2 -2
- package/dist/native/bridge/WebBridge.d.ts +98 -0
- package/dist/native/bridge/WebBridge.js +40 -6
- package/dist/native/bridge/constants/NativeInterfaces.d.ts +391 -0
- package/dist/native/bridge/errors.d.ts +67 -0
- package/dist/native/bridge/errors.js +66 -151
- package/dist/native/bridge/hooks/index.d.ts +13 -0
- package/dist/native/bridge/hooks/index.js +0 -6
- package/dist/native/bridge/hooks/useAI.d.ts +1 -0
- package/dist/native/bridge/hooks/useAI.js +3 -1
- package/dist/native/bridge/hooks/useCamera.d.ts +86 -0
- package/dist/native/bridge/hooks/useCamera.js +35 -6
- package/dist/native/bridge/hooks/useDataProtection.d.ts +17 -0
- package/dist/native/bridge/hooks/useDeviceInfo.d.ts +34 -0
- package/dist/native/bridge/hooks/useDeviceInfo.js +5 -0
- package/dist/native/bridge/hooks/useFilePicker.d.ts +53 -0
- package/dist/native/bridge/hooks/useFilePicker.js +13 -0
- package/dist/native/bridge/hooks/useGoogleSignIn.d.ts +12 -0
- package/dist/native/bridge/hooks/useHapticFeedback.d.ts +76 -0
- package/dist/native/bridge/hooks/useHapticFeedback.js +6 -1
- package/dist/native/bridge/hooks/useIntent.d.ts +33 -0
- package/dist/native/bridge/hooks/useIntent.js +2 -0
- package/dist/native/bridge/hooks/useNativeTransition.d.ts +53 -0
- package/dist/native/bridge/hooks/useNativeTransition.js +12 -5
- package/dist/native/bridge/hooks/useNetworkStatus.d.ts +22 -0
- package/dist/native/bridge/hooks/useNetworkStatus.js +7 -0
- package/dist/native/bridge/hooks/useNotification.d.ts +83 -0
- package/dist/native/bridge/hooks/useNotification.js +81 -34
- package/dist/native/bridge/hooks/useSafeArea.d.ts +12 -0
- package/dist/native/bridge/hooks/useSafeArea.js +8 -0
- package/dist/native/bridge/hooks/useVideoStream.d.ts +67 -0
- package/dist/native/bridge/hooks/useVideoStream.js +38 -52
- package/dist/native/bridge/hooks/utils.d.ts +4 -0
- package/dist/native/bridge/hooks.d.ts +1 -0
- package/dist/native/bridge/perf/collectors/ApiCollector.d.ts +30 -0
- package/dist/native/bridge/perf/collectors/ApiCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/CacheCollector.d.ts +43 -0
- package/dist/native/bridge/perf/collectors/CacheCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/HookCollector.d.ts +37 -0
- package/dist/native/bridge/perf/collectors/HookCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/InsightsCollector.d.ts +103 -0
- package/dist/native/bridge/perf/collectors/InsightsCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/InteractionCollector.d.ts +53 -0
- package/dist/native/bridge/perf/collectors/InteractionCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/KeyboardCollector.d.ts +30 -0
- package/dist/native/bridge/perf/collectors/KeyboardCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/NavigationCollector.d.ts +37 -0
- package/dist/native/bridge/perf/collectors/NavigationCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/NetworkTimingCollector.d.ts +30 -0
- package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/RenderCollector.d.ts +47 -0
- package/dist/native/bridge/perf/collectors/RenderCollector.js +8 -0
- package/dist/native/bridge/perf/collectors/ScrollCollector.d.ts +29 -0
- package/dist/native/bridge/perf/collectors/ScrollCollector.js +4 -0
- package/dist/native/bridge/perf/collectors/ThreadCollector.d.ts +31 -0
- package/dist/native/bridge/perf/collectors/ThreadCollector.js +4 -0
- package/dist/native/bridge/perf/core/constants.d.ts +76 -0
- package/dist/native/bridge/perf/core/measure.d.ts +39 -0
- package/dist/native/bridge/perf/core/measure.js +4 -0
- package/dist/native/bridge/perf/core/session.d.ts +49 -0
- package/dist/native/bridge/perf/core/session.js +4 -0
- package/dist/native/bridge/perf/core/store.d.ts +37 -0
- package/dist/native/bridge/perf/core/store.js +4 -0
- package/dist/native/bridge/perf/core/summary.d.ts +60 -0
- package/dist/native/bridge/perf/core/traceExport.d.ts +10 -0
- package/dist/native/bridge/perf/core/waterfalls.d.ts +2 -0
- package/dist/native/bridge/perf/index.d.ts +63 -0
- package/dist/native/bridge/perf/index.js +4 -0
- package/dist/native/bridge/safeArea.d.ts +11 -0
- package/dist/native/bridge/safeArea.js +2 -0
- package/dist/native/bridge/useBaseHook.d.ts +137 -0
- package/dist/native/bridge/useBaseHook.js +34 -4
- package/dist/native/bridge/utils/CameraUtils.d.ts +94 -0
- package/dist/native/bridge/utils/CameraUtils.js +4 -0
- package/dist/native/bridge/utils/FileObjectConverter.d.ts +36 -0
- package/dist/native/bridge/utils/NativeBridge.d.ts +270 -0
- package/dist/native/bridge/utils/NativeBridge.js +10 -0
- package/dist/native/buildAndroid/index.js +1 -1
- package/dist/native/buildAppAndroid.js +9 -0
- package/dist/native/buildAppIos.js +16 -1
- package/dist/native/buildErrorFormat.js +57 -0
- package/dist/native/buildIos/config.js +15 -1
- package/dist/native/buildIos/index.js +1 -1
- package/dist/native/buildIos/plugins.js +10 -1
- package/dist/native/iosnativeWebView/CoreLogic/Package.swift +36 -0
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Camera/VideoStreamState.swift +1 -1
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Camera/VideoStreamStateMachine.swift +6 -4
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/BootTimingUtility.swift +3 -3
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/FrameworkServerUtils.swift +14 -9
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NetworkMonitor.swift +11 -9
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NotificationHandlerProvider.swift +1 -1
- package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/URLWhitelistManager.swift +7 -7
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/AnyCodableTests.swift +154 -0
- package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/BootTimingUtilityTests.swift +23 -5
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/CatalystConstantsTests.swift +192 -0
- package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/ConfigMappingTests.swift +1 -1
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/FrameworkServerUtilsErrorPathTests.swift +106 -0
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/FrameworkServerUtilsLoopbackTests.swift +243 -0
- package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/FrameworkServerUtilsTests.swift +1 -1
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/NetworkMonitorTests.swift +119 -0
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/NotificationHandlerProviderTests.swift +59 -0
- package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/NotificationHandlerTests.swift +1 -1
- package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/URLWhitelistManagerTests.swift +1 -1
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/VideoStreamStateMachineTests.swift +171 -0
- package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/VideoStreamStateTests.swift +91 -0
- package/dist/native/iosnativeWebView/Package.swift +10 -9
- package/dist/native/iosnativeWebView/Sources/CatalystNotifications/LocalNotificationHandler.swift +7 -2
- package/dist/native/iosnativeWebView/Sources/CatalystNotifications/NotificationManager.swift +1 -2
- package/dist/native/iosnativeWebView/Sources/CatalystNotifications/PushNotificationHandler.swift +5 -4
- package/dist/native/iosnativeWebView/Sources/Core/Camera/CameraSessionManager.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/HoldController.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/NativeCameraManager.swift +6 -5
- package/dist/native/iosnativeWebView/Sources/Core/Camera/ZoomController.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/Plugins/PluginBridge.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +31 -30
- package/dist/native/iosnativeWebView/Sources/Core/Utils/CameraTransportUtils.swift +2 -1
- package/dist/native/iosnativeWebView/Sources/Core/Utils/DeviceInfoUtils.swift +1 -1
- package/dist/native/iosnativeWebView/Sources/Core/Utils/FilePickerHandler.swift +22 -19
- package/dist/native/iosnativeWebView/Sources/Core/Utils/ImageHandler.swift +40 -39
- package/dist/native/iosnativeWebView/Sources/Core/Utils/PerfEventBuffer.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/ResourceURLProtocol.swift +15 -15
- package/dist/native/iosnativeWebView/Sources/Core/Utils/WebKitConfig.swift +4 -3
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeCommandHandler.swift +6 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeDelegateHandler.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeFileHandler.swift +2 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeJavaScriptInterface.swift +2 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +3 -5
- package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +20 -13
- package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashView.swift +6 -5
- package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashViewModel.swift +14 -13
- package/dist/native/iosnativeWebView/Sources/Core/WebView/TransitionManager.swift +3 -3
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +9 -8
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewModel.swift +7 -6
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +24 -25
- package/dist/native/iosnativeWebView/iosnativeWebView/AppDelegate.swift +6 -1
- package/dist/native/iosnativeWebView/iosnativeWebView/ContentView.swift +1 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebViewApp.swift +4 -0
- package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +2 -22
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/BridgeMessageValidatorTests.swift +1 -0
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/CacheManagerTests.swift +1 -0
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/FilePickerHandlerTests.swift +2 -1
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/NativeBridgeTests.swift +15 -9
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/WebViewTests.swift +1 -0
- package/dist/native/setupEmulatorIos.js +2 -2
- package/dist/native/terminalProgress.js +17 -17
- package/dist/router/ClientRouter.d.ts +8 -0
- package/dist/router/ClientRouter.js +13 -11
- package/dist/router/ServerRouter.d.ts +13 -0
- package/dist/router/ServerRouter.js +19 -7
- package/dist/scripts/build.js +14 -2
- package/dist/scripts/loadEnvironmentVariables.js +3 -2
- package/dist/scripts/plugins.js +1 -1
- package/dist/scripts/preServerInit.js +49 -3
- package/dist/scripts/preflight.js +111 -0
- package/dist/scripts/scriptUtils.js +46 -1
- package/dist/scripts/serve.js +7 -3
- package/dist/scripts/start.js +8 -3
- package/dist/server/expressServer.d.ts +1 -0
- package/dist/server/expressServer.js +247 -271
- package/dist/server/manifestCache.d.ts +2 -0
- package/dist/server/manifestCache.js +25 -33
- package/dist/server/renderer/ChunkExtractor.d.ts +44 -0
- package/dist/server/renderer/ChunkExtractor.js +113 -125
- package/dist/server/renderer/document/Body.d.ts +21 -0
- package/dist/server/renderer/document/Body.jsx +45 -45
- package/dist/server/renderer/document/FastRefresh.d.ts +3 -0
- package/dist/server/renderer/document/FastRefresh.jsx +7 -13
- package/dist/server/renderer/document/Head.d.ts +20 -0
- package/dist/server/renderer/document/Head.jsx +32 -32
- package/dist/server/renderer/document/index.d.ts +2 -0
- package/dist/server/renderer/document/index.jsx +2 -2
- package/dist/server/renderer/extract.d.ts +67 -0
- package/dist/server/renderer/extract.js +92 -89
- package/dist/server/renderer/handler.d.ts +2 -0
- package/dist/server/renderer/handler.jsx +401 -404
- package/dist/server/renderer/index.d.ts +2 -0
- package/dist/server/renderer/index.js +5 -8
- package/dist/server/renderer/render.d.ts +35 -0
- package/dist/server/renderer/render.js +25 -32
- package/dist/server/utils/botDetectionMiddleware.d.ts +1 -0
- package/dist/server/utils/botDetectionMiddleware.js +33 -23
- package/dist/server/utils/cjsRequire.d.ts +8 -0
- package/dist/server/utils/cjsRequire.js +2 -2
- package/dist/server/utils/userAgentUtil.d.ts +7 -0
- package/dist/server/utils/userAgentUtil.js +68 -71
- package/dist/server/utils/validator.d.ts +31 -0
- package/dist/server/utils/validator.js +133 -158
- package/dist/vite/inject-cache-key-plugin.js +3 -27
- package/dist/vite/moduleAliases.js +36 -0
- package/dist/vite/node-loader.mjs +2 -29
- package/dist/vite/resolveDevServerConfig.js +4 -1
- package/dist/vite/vite.config.js +2 -29
- package/dist/web-router/components/MetaTag.d.ts +4 -0
- package/dist/web-router/components/MetaTag.jsx +26 -28
- package/dist/web-router/components/MetaTag.test.jsx +100 -0
- package/dist/web-router/components/RouterDataProvider.d.ts +96 -0
- package/dist/web-router/components/RouterDataProvider.jsx +260 -259
- package/dist/web-router/components/RouterDataProvider.server.test.jsx +98 -0
- package/dist/web-router/components/RouterDataProvider.test.jsx +310 -0
- package/dist/web-router/components/Split.d.ts +74 -0
- package/dist/web-router/components/Split.jsx +147 -156
- package/dist/web-router/components/Split.server.test.jsx +52 -0
- package/dist/web-router/components/Split.test.jsx +167 -0
- package/dist/web-router/components/SplitInview.d.ts +22 -0
- package/dist/web-router/components/SplitInview.jsx +78 -89
- package/dist/web-router/components/SplitInview.test.jsx +112 -0
- package/dist/web-router/components/SsrRequestContext.d.ts +20 -0
- package/dist/web-router/components/SsrRequestContext.jsx +17 -7
- package/dist/web-router/components/SsrRequestContext.test.jsx +53 -0
- package/dist/web-router/context.d.ts +15 -0
- package/dist/web-router/context.jsx +5 -5
- package/dist/web-router/context.test.jsx +10 -0
- package/dist/web-router/utils/metaDataUtils.d.ts +24 -0
- package/dist/web-router/utils/metaDataUtils.jsx +86 -86
- package/dist/web-router/utils/metaDataUtils.test.jsx +188 -0
- package/dist/web-router/vitest.setup.js +12 -0
- package/mcp_v2/knowledge-base.json +115 -17
- package/mcp_v2/mcp.js +141 -3
- package/mcp_v2/package-lock.json +2031 -0
- package/mcp_v2/package.json +13 -2
- package/mcp_v2/scripts/copyErrorsIndex.cjs +34 -0
- package/mcp_v2/test/errors.test.ts +123 -0
- package/mcp_v2/test/github.test.ts +177 -0
- package/mcp_v2/tools/errors.d.ts +20 -0
- package/mcp_v2/tools/errors.js +63 -0
- package/mcp_v2/tools/github.d.ts +41 -0
- package/mcp_v2/tools/github.js +231 -0
- package/mcp_v2/vitest.config.mjs +22 -0
- package/package.json +60 -11
- package/test/errors/docsDrift.test.ts +113 -0
- package/test/errors/index.test.ts +200 -0
- package/test/errors/registry.test.ts +108 -0
- package/test/scripts/preflight.test.ts +118 -0
- package/test/server/ChunkExtractor.test.ts +97 -0
- package/test/server/extract.test.ts +128 -0
- package/test/server/fixtures/template/server/document.jsx +19 -0
- package/test/server/fixtures/template/server/index.js +10 -0
- package/test/server/fixtures/template/src/js/containers/App/index.jsx +33 -0
- package/test/server/fixtures/template/src/js/routes/index.jsx +72 -0
- package/test/server/fixtures/template/src/js/routes/utils.jsx +39 -0
- package/test/server/fixtures/template/src/js/store/index.js +19 -0
- package/test/server/handler.assets.test.ts +330 -0
- package/test/server/handler.test.ts +208 -0
- package/test/server/manifestCache.test.ts +71 -0
- package/test/server/render.test.ts +71 -0
- package/test/server/scriptUtils.test.ts +103 -0
- package/test/server/userAgentUtil.test.ts +48 -0
- package/test/server/validator.test.ts +225 -0
- package/test/vite/resolveDevServerConfig.test.js +4 -1
- package/tsconfig.test.json +23 -0
- package/vitest.config.ts +93 -0
- package/dist/caching.js +0 -1
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/DeviceInfoUtilsTest.kt +0 -187
- package/dist/native/bridge/standardizedHooks.js +0 -611
- package/dist/router.js +0 -1
- package/dist/scripts/validator.js +0 -149
- package/dist/web-router/hooks.jsx +0 -72
- package/dist/web-router/types/components/MetaTag.d.ts +0 -2
- package/dist/web-router/types/components/RouterDataProvider.d.ts +0 -95
- package/dist/web-router/types/context.d.ts +0 -14
- package/dist/web-router/types/hooks.d.ts +0 -1
- package/dist/web-router/types/index.d.ts +0 -3
- package/dist/web-router/types/utils/metaDataUtils.d.ts +0 -40
- /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Constants/CatalystConstants.swift +0 -0
- /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Constants/ConfigConstants.swift +0 -0
- /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Notifications/NotificationModels.swift +0 -0
- /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Protocols/NotificationHandlerProtocol.swift +0 -0
- /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NullNotificationHandler.swift +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
package io.yourname.androidproject.camera
|
|
2
|
+
|
|
3
|
+
import android.webkit.WebView
|
|
4
|
+
import org.json.JSONObject
|
|
5
|
+
import org.junit.Assert.assertNotNull
|
|
6
|
+
import org.junit.Assert.assertNull
|
|
7
|
+
import org.junit.Test
|
|
8
|
+
import org.mockito.kotlin.any
|
|
9
|
+
import org.mockito.kotlin.mock
|
|
10
|
+
import org.mockito.kotlin.verify
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unit tests for ViewfinderMapper (Android coverage batch 3), previously
|
|
14
|
+
* entirely untested (0/30 lines).
|
|
15
|
+
*
|
|
16
|
+
* Both functions are pure coordinate math with a single mockable
|
|
17
|
+
* collaborator call (WebView.getLocationOnScreen(IntArray)). All lines
|
|
18
|
+
* (the guard branches, the scale/offset math, and the success/failure
|
|
19
|
+
* paths of parseViewfinderRect) execute under test and are covered by
|
|
20
|
+
* jacoco -- but the *values* the math produces cannot be asserted here:
|
|
21
|
+
* android.graphics.RectF is a stub under this project's mockable
|
|
22
|
+
* android.jar (isReturnDefaultValues=true, confirmed empirically -- a
|
|
23
|
+
* `RectF(10f, 20f, 110f, 70f)` constructed in a test reads back left/top/
|
|
24
|
+
* right/bottom as 0.0, since the constructor body that assigns those
|
|
25
|
+
* public fields never runs). Per the PerfEventBufferTest/MetricsMonitorTest
|
|
26
|
+
* precedent of documenting and moving on rather than reaching for
|
|
27
|
+
* Robolectric, this file verifies null/non-null outcomes and observable
|
|
28
|
+
* collaborator interactions (webView.getLocationOnScreen being invoked)
|
|
29
|
+
* instead of exact coordinate values.
|
|
30
|
+
*/
|
|
31
|
+
class ViewfinderMapperTest {
|
|
32
|
+
|
|
33
|
+
// ============================================================
|
|
34
|
+
// parseViewfinderRect
|
|
35
|
+
// ============================================================
|
|
36
|
+
|
|
37
|
+
@Test
|
|
38
|
+
fun `parseViewfinderRect returns a non-null pair and reads the WebView origin on well-formed JSON`() {
|
|
39
|
+
val json = JSONObject().apply {
|
|
40
|
+
put("x", 10.0)
|
|
41
|
+
put("y", 20.0)
|
|
42
|
+
put("width", 100.0)
|
|
43
|
+
put("height", 50.0)
|
|
44
|
+
}
|
|
45
|
+
val webView = mock<WebView>()
|
|
46
|
+
|
|
47
|
+
val result = ViewfinderMapper.parseViewfinderRect(json, webView)
|
|
48
|
+
|
|
49
|
+
assertNotNull(result)
|
|
50
|
+
verify(webView).getLocationOnScreen(any())
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Test
|
|
54
|
+
fun `parseViewfinderRect returns null when a required field is missing`() {
|
|
55
|
+
val json = JSONObject().apply {
|
|
56
|
+
put("x", 10.0)
|
|
57
|
+
put("y", 20.0)
|
|
58
|
+
// "width" and "height" deliberately omitted -- json.getDouble
|
|
59
|
+
// throws a JSONException, caught and mapped to null.
|
|
60
|
+
}
|
|
61
|
+
val webView = mock<WebView>()
|
|
62
|
+
|
|
63
|
+
val result = ViewfinderMapper.parseViewfinderRect(json, webView)
|
|
64
|
+
|
|
65
|
+
assertNull(result)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Test
|
|
69
|
+
fun `parseViewfinderRect does not call getLocationOnScreen when JSON parsing fails first`() {
|
|
70
|
+
val json = JSONObject() // no fields at all
|
|
71
|
+
val webView = mock<WebView>()
|
|
72
|
+
|
|
73
|
+
ViewfinderMapper.parseViewfinderRect(json, webView)
|
|
74
|
+
|
|
75
|
+
// x is read before webView.getLocationOnScreen is called -- an
|
|
76
|
+
// empty JSON object throws on the very first getDouble("x").
|
|
77
|
+
org.mockito.Mockito.verifyNoInteractions(webView)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ============================================================
|
|
81
|
+
// mapBarcodeToScreen
|
|
82
|
+
// ============================================================
|
|
83
|
+
|
|
84
|
+
@Test
|
|
85
|
+
fun `mapBarcodeToScreen returns null when previewWidth is zero`() {
|
|
86
|
+
val result = ViewfinderMapper.mapBarcodeToScreen(
|
|
87
|
+
boxLeft = 0, boxTop = 0, boxRight = 100, boxBottom = 100,
|
|
88
|
+
imageWidth = 640, imageHeight = 480,
|
|
89
|
+
previewWidth = 0f, previewHeight = 800f
|
|
90
|
+
)
|
|
91
|
+
assertNull(result)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Test
|
|
95
|
+
fun `mapBarcodeToScreen returns null when previewHeight is zero`() {
|
|
96
|
+
val result = ViewfinderMapper.mapBarcodeToScreen(
|
|
97
|
+
boxLeft = 0, boxTop = 0, boxRight = 100, boxBottom = 100,
|
|
98
|
+
imageWidth = 640, imageHeight = 480,
|
|
99
|
+
previewWidth = 600f, previewHeight = 0f
|
|
100
|
+
)
|
|
101
|
+
assertNull(result)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Test
|
|
105
|
+
fun `mapBarcodeToScreen returns null when imageWidth is zero`() {
|
|
106
|
+
val result = ViewfinderMapper.mapBarcodeToScreen(
|
|
107
|
+
boxLeft = 0, boxTop = 0, boxRight = 100, boxBottom = 100,
|
|
108
|
+
imageWidth = 0, imageHeight = 480,
|
|
109
|
+
previewWidth = 600f, previewHeight = 800f
|
|
110
|
+
)
|
|
111
|
+
assertNull(result)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@Test
|
|
115
|
+
fun `mapBarcodeToScreen returns null when imageHeight is zero`() {
|
|
116
|
+
val result = ViewfinderMapper.mapBarcodeToScreen(
|
|
117
|
+
boxLeft = 0, boxTop = 0, boxRight = 100, boxBottom = 100,
|
|
118
|
+
imageWidth = 640, imageHeight = 0,
|
|
119
|
+
previewWidth = 600f, previewHeight = 800f
|
|
120
|
+
)
|
|
121
|
+
assertNull(result)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@Test
|
|
125
|
+
fun `mapBarcodeToScreen returns non-null for valid non-square dimensions, exercising the FILL_CENTER scale math`() {
|
|
126
|
+
val result = ViewfinderMapper.mapBarcodeToScreen(
|
|
127
|
+
boxLeft = 100, boxTop = 100, boxRight = 200, boxBottom = 200,
|
|
128
|
+
imageWidth = 640, imageHeight = 480,
|
|
129
|
+
previewWidth = 400f, previewHeight = 400f
|
|
130
|
+
)
|
|
131
|
+
assertNotNull(result)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@Test
|
|
135
|
+
fun `mapBarcodeToScreen returns non-null when preview and image aspect ratios match`() {
|
|
136
|
+
val result = ViewfinderMapper.mapBarcodeToScreen(
|
|
137
|
+
boxLeft = 0, boxTop = 0, boxRight = 640, boxBottom = 480,
|
|
138
|
+
imageWidth = 640, imageHeight = 480,
|
|
139
|
+
previewWidth = 320f, previewHeight = 240f
|
|
140
|
+
)
|
|
141
|
+
assertNotNull(result)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
package io.yourname.androidproject.camera
|
|
2
|
+
|
|
3
|
+
import android.animation.ValueAnimator
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import androidx.camera.core.Camera
|
|
6
|
+
import androidx.camera.core.CameraControl
|
|
7
|
+
import androidx.camera.core.CameraInfo
|
|
8
|
+
import androidx.camera.core.ZoomState
|
|
9
|
+
import androidx.lifecycle.LiveData
|
|
10
|
+
import org.junit.After
|
|
11
|
+
import org.junit.Assert.assertEquals
|
|
12
|
+
import org.junit.Assert.assertFalse
|
|
13
|
+
import org.junit.Assert.assertTrue
|
|
14
|
+
import org.junit.Before
|
|
15
|
+
import org.junit.Test
|
|
16
|
+
import org.mockito.MockedStatic
|
|
17
|
+
import org.mockito.Mockito.mockStatic
|
|
18
|
+
import org.mockito.kotlin.any
|
|
19
|
+
import org.mockito.kotlin.argumentCaptor
|
|
20
|
+
import org.mockito.kotlin.doReturn
|
|
21
|
+
import org.mockito.kotlin.mock
|
|
22
|
+
import org.mockito.kotlin.verify
|
|
23
|
+
import org.mockito.kotlin.whenever
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Unit tests for ZoomController (Android coverage batch 4), previously
|
|
27
|
+
* entirely untested (0/~79 lines).
|
|
28
|
+
*
|
|
29
|
+
* Constructor takes only a Context (to build a ScaleGestureDetector) plus
|
|
30
|
+
* a VideoStreamStateMachine and a callback -- all safe to construct
|
|
31
|
+
* because the mockable android.jar strips Android constructors to no-ops.
|
|
32
|
+
* The ScaleGestureDetector-driven pinch-to-zoom path (onTouchEvent /
|
|
33
|
+
* SimpleOnScaleGestureListener.onScale) is NOT exercised here: it requires
|
|
34
|
+
* a real ScaleGestureDetector to actually parse a MotionEvent stream and
|
|
35
|
+
* invoke the listener, which the mockable jar's stub GestureDetector does
|
|
36
|
+
* not do -- there is no seam to inject a fake detector (it's a private val
|
|
37
|
+
* built in the constructor). That gap mirrors this project's established
|
|
38
|
+
* precedent of leaving Android-internal event-dispatch machinery
|
|
39
|
+
* unexercised (see HoldControllerTest's Handler/Looper note) rather than
|
|
40
|
+
* pulling in Robolectric.
|
|
41
|
+
*
|
|
42
|
+
* Covered instead: applyZoomMultiplier() (no-camera / no-zoomState guards
|
|
43
|
+
* and the real clamp+setZoomRatio+callback path), onAutoZoomSuggestion()'s
|
|
44
|
+
* zoom-only-up guard, debounce/confirm-frame counting, and the animated
|
|
45
|
+
* commit branch, cancelZoomAnimation(), and currentMaxZoomRatio().
|
|
46
|
+
*
|
|
47
|
+
* ValueAnimator.ofFloat(...) returns null under the mockable jar (a static
|
|
48
|
+
* factory method, same shape as MetricsMonitorTest's
|
|
49
|
+
* Choreographer.getInstance() problem) -- mockStatic(ValueAnimator) is
|
|
50
|
+
* installed for the animated-commit tests and closed in tearDown(),
|
|
51
|
+
* stubbing ofFloat(...) to return a mocked ValueAnimator so
|
|
52
|
+
* onAutoZoomSuggestion()'s `.apply { ... start() }` block and the
|
|
53
|
+
* addUpdateListener(...) callback body are both exercisable by manually
|
|
54
|
+
* invoking the captured listener, mirroring TorchControllerTest's
|
|
55
|
+
* captured-Runnable pattern.
|
|
56
|
+
*/
|
|
57
|
+
class ZoomControllerTest {
|
|
58
|
+
|
|
59
|
+
private lateinit var valueAnimatorMock: MockedStatic<ValueAnimator>
|
|
60
|
+
private val context = mock<Context>()
|
|
61
|
+
private val stateMachine = mock<VideoStreamStateMachine>()
|
|
62
|
+
|
|
63
|
+
private val zoomEvents = mutableListOf<Triple<Float, Float, Float>>()
|
|
64
|
+
private fun onZoomChanged(zoomLevel: Float, minZoom: Float, maxZoom: Float) {
|
|
65
|
+
zoomEvents.add(Triple(zoomLevel, minZoom, maxZoom))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private fun newController() = ZoomController(context, stateMachine, ::onZoomChanged)
|
|
69
|
+
|
|
70
|
+
@Before
|
|
71
|
+
fun setUp() {
|
|
72
|
+
zoomEvents.clear()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@After
|
|
76
|
+
fun tearDown() {
|
|
77
|
+
if (::valueAnimatorMock.isInitialized) {
|
|
78
|
+
valueAnimatorMock.close()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private fun mockCamera(zoomRatio: Float, minZoom: Float, maxZoom: Float): Camera {
|
|
83
|
+
val zoomState = mock<ZoomState> {
|
|
84
|
+
on { getZoomRatio() } doReturn zoomRatio
|
|
85
|
+
on { getMinZoomRatio() } doReturn minZoom
|
|
86
|
+
on { getMaxZoomRatio() } doReturn maxZoom
|
|
87
|
+
}
|
|
88
|
+
@Suppress("UNCHECKED_CAST")
|
|
89
|
+
val zoomStateLiveData = mock<LiveData<ZoomState>> {
|
|
90
|
+
on { getValue() } doReturn zoomState
|
|
91
|
+
}
|
|
92
|
+
val cameraInfo = mock<CameraInfo> {
|
|
93
|
+
on { getZoomState() } doReturn zoomStateLiveData
|
|
94
|
+
}
|
|
95
|
+
val cameraControl = mock<CameraControl>()
|
|
96
|
+
return mock {
|
|
97
|
+
on { getCameraInfo() } doReturn cameraInfo
|
|
98
|
+
on { getCameraControl() } doReturn cameraControl
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================
|
|
103
|
+
// applyZoomMultiplier
|
|
104
|
+
// ============================================================
|
|
105
|
+
|
|
106
|
+
@Test
|
|
107
|
+
fun `applyZoomMultiplier with no camera attached is a no-op`() {
|
|
108
|
+
val controller = newController()
|
|
109
|
+
|
|
110
|
+
controller.applyZoomMultiplier(2.0f)
|
|
111
|
+
|
|
112
|
+
assertTrue(zoomEvents.isEmpty())
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@Test
|
|
116
|
+
fun `applyZoomMultiplier with a null zoomState value is a no-op`() {
|
|
117
|
+
val zoomStateLiveData = mock<LiveData<ZoomState>>()
|
|
118
|
+
whenever(zoomStateLiveData.value).thenReturn(null)
|
|
119
|
+
val cameraInfo = mock<CameraInfo> {
|
|
120
|
+
on { getZoomState() } doReturn zoomStateLiveData
|
|
121
|
+
}
|
|
122
|
+
val camera = mock<Camera> { on { getCameraInfo() } doReturn cameraInfo }
|
|
123
|
+
val controller = newController()
|
|
124
|
+
controller.attachCamera(camera)
|
|
125
|
+
|
|
126
|
+
controller.applyZoomMultiplier(2.0f)
|
|
127
|
+
|
|
128
|
+
assertTrue(zoomEvents.isEmpty())
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@Test
|
|
132
|
+
fun `applyZoomMultiplier clamps to maxZoomRatio and fires the callback`() {
|
|
133
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 5.0f)
|
|
134
|
+
val controller = newController()
|
|
135
|
+
controller.attachCamera(camera)
|
|
136
|
+
|
|
137
|
+
controller.applyZoomMultiplier(10.0f)
|
|
138
|
+
|
|
139
|
+
verify(camera.cameraControl).setZoomRatio(5.0f)
|
|
140
|
+
assertEquals(listOf(Triple(5.0f, 1.0f, 5.0f)), zoomEvents)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@Test
|
|
144
|
+
fun `applyZoomMultiplier clamps to minZoomRatio when below range`() {
|
|
145
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 5.0f)
|
|
146
|
+
val controller = newController()
|
|
147
|
+
controller.attachCamera(camera)
|
|
148
|
+
|
|
149
|
+
controller.applyZoomMultiplier(0.1f)
|
|
150
|
+
|
|
151
|
+
verify(camera.cameraControl).setZoomRatio(1.0f)
|
|
152
|
+
assertEquals(listOf(Triple(1.0f, 1.0f, 5.0f)), zoomEvents)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@Test
|
|
156
|
+
fun `applyZoomMultiplier within range passes the multiplier through unchanged`() {
|
|
157
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 5.0f)
|
|
158
|
+
val controller = newController()
|
|
159
|
+
controller.attachCamera(camera)
|
|
160
|
+
|
|
161
|
+
controller.applyZoomMultiplier(3.0f)
|
|
162
|
+
|
|
163
|
+
verify(camera.cameraControl).setZoomRatio(3.0f)
|
|
164
|
+
assertEquals(listOf(Triple(3.0f, 1.0f, 5.0f)), zoomEvents)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@Test
|
|
168
|
+
fun `setZoom delegates to applyZoomMultiplier`() {
|
|
169
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 5.0f)
|
|
170
|
+
val controller = newController()
|
|
171
|
+
controller.attachCamera(camera)
|
|
172
|
+
|
|
173
|
+
controller.setZoom(2.0f)
|
|
174
|
+
|
|
175
|
+
verify(camera.cameraControl).setZoomRatio(2.0f)
|
|
176
|
+
assertEquals(listOf(Triple(2.0f, 1.0f, 5.0f)), zoomEvents)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ============================================================
|
|
180
|
+
// detachCamera
|
|
181
|
+
// ============================================================
|
|
182
|
+
|
|
183
|
+
@Test
|
|
184
|
+
fun `detachCamera clears the camera so subsequent zoom calls are no-ops`() {
|
|
185
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 5.0f)
|
|
186
|
+
val controller = newController()
|
|
187
|
+
controller.attachCamera(camera)
|
|
188
|
+
|
|
189
|
+
controller.detachCamera()
|
|
190
|
+
controller.applyZoomMultiplier(2.0f)
|
|
191
|
+
|
|
192
|
+
assertTrue(zoomEvents.isEmpty())
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ============================================================
|
|
196
|
+
// onAutoZoomSuggestion -- guards
|
|
197
|
+
// ============================================================
|
|
198
|
+
|
|
199
|
+
@Test
|
|
200
|
+
fun `onAutoZoomSuggestion with no camera attached returns false`() {
|
|
201
|
+
val controller = newController()
|
|
202
|
+
|
|
203
|
+
val result = controller.onAutoZoomSuggestion(3.0f)
|
|
204
|
+
|
|
205
|
+
assertFalse(result)
|
|
206
|
+
assertTrue(zoomEvents.isEmpty())
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@Test
|
|
210
|
+
fun `onAutoZoomSuggestion ignores a suggestion that would zoom out`() {
|
|
211
|
+
val camera = mockCamera(zoomRatio = 3.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
212
|
+
val controller = newController()
|
|
213
|
+
controller.attachCamera(camera)
|
|
214
|
+
|
|
215
|
+
val result = controller.onAutoZoomSuggestion(2.0f)
|
|
216
|
+
|
|
217
|
+
assertFalse(result)
|
|
218
|
+
assertTrue(zoomEvents.isEmpty())
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@Test
|
|
222
|
+
fun `onAutoZoomSuggestion ignores a suggestion equal to the current ratio`() {
|
|
223
|
+
val camera = mockCamera(zoomRatio = 3.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
224
|
+
val controller = newController()
|
|
225
|
+
controller.attachCamera(camera)
|
|
226
|
+
|
|
227
|
+
val result = controller.onAutoZoomSuggestion(3.0f)
|
|
228
|
+
|
|
229
|
+
assertFalse(result)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ============================================================
|
|
233
|
+
// onAutoZoomSuggestion -- debounce
|
|
234
|
+
// ============================================================
|
|
235
|
+
|
|
236
|
+
@Test
|
|
237
|
+
fun `onAutoZoomSuggestion requires two consecutive matching frames before committing`() {
|
|
238
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
239
|
+
val controller = newController()
|
|
240
|
+
controller.attachCamera(camera)
|
|
241
|
+
|
|
242
|
+
val firstFrame = controller.onAutoZoomSuggestion(4.0f)
|
|
243
|
+
assertFalse("first frame should only start debounce, not commit", firstFrame)
|
|
244
|
+
assertTrue(zoomEvents.isEmpty())
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@Test
|
|
248
|
+
fun `onAutoZoomSuggestion resets debounce when the target changes beyond tolerance`() {
|
|
249
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
250
|
+
val controller = newController()
|
|
251
|
+
controller.attachCamera(camera)
|
|
252
|
+
|
|
253
|
+
controller.onAutoZoomSuggestion(4.0f)
|
|
254
|
+
// Jumps well outside SUGGESTION_TOLERANCE (0.1f) -- restarts the
|
|
255
|
+
// debounce counter at 1 rather than confirming.
|
|
256
|
+
val secondFrame = controller.onAutoZoomSuggestion(6.0f)
|
|
257
|
+
|
|
258
|
+
assertFalse(secondFrame)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@Test
|
|
262
|
+
fun `onAutoZoomSuggestion resets debounce after a zoom-out-guard rejection`() {
|
|
263
|
+
val camera = mockCamera(zoomRatio = 3.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
264
|
+
val controller = newController()
|
|
265
|
+
controller.attachCamera(camera)
|
|
266
|
+
|
|
267
|
+
// First build up one confirm frame toward 5.0.
|
|
268
|
+
controller.onAutoZoomSuggestion(5.0f)
|
|
269
|
+
// Now a rejected (zoom-out) suggestion resets consecutiveSuggestionCount to 0.
|
|
270
|
+
controller.onAutoZoomSuggestion(2.0f)
|
|
271
|
+
|
|
272
|
+
valueAnimatorMock = mockStatic(ValueAnimator::class.java)
|
|
273
|
+
val animator = mock<ValueAnimator>()
|
|
274
|
+
valueAnimatorMock.`when`<ValueAnimator> { ValueAnimator.ofFloat(any(), any()) }.thenReturn(animator)
|
|
275
|
+
|
|
276
|
+
// Suggesting 5.0 again should require a fresh two-frame confirm,
|
|
277
|
+
// not just one more (proving the counter was actually reset).
|
|
278
|
+
val secondAttemptFirstFrame = controller.onAutoZoomSuggestion(5.0f)
|
|
279
|
+
assertFalse("counter should have been reset by the rejected suggestion", secondAttemptFirstFrame)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ============================================================
|
|
283
|
+
// onAutoZoomSuggestion -- confirmed / animated commit
|
|
284
|
+
// ============================================================
|
|
285
|
+
|
|
286
|
+
@Test
|
|
287
|
+
fun `onAutoZoomSuggestion commits and animates after enough consecutive matching frames`() {
|
|
288
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
289
|
+
val controller = newController()
|
|
290
|
+
controller.attachCamera(camera)
|
|
291
|
+
|
|
292
|
+
valueAnimatorMock = mockStatic(ValueAnimator::class.java)
|
|
293
|
+
val animator = mock<ValueAnimator>()
|
|
294
|
+
valueAnimatorMock.`when`<ValueAnimator> { ValueAnimator.ofFloat(1.0f, 4.0f) }.thenReturn(animator)
|
|
295
|
+
|
|
296
|
+
controller.onAutoZoomSuggestion(4.0f) // frame 1 -- debounce only
|
|
297
|
+
val committed = controller.onAutoZoomSuggestion(4.0f) // frame 2 -- confirmed
|
|
298
|
+
|
|
299
|
+
assertTrue(committed)
|
|
300
|
+
verify(animator).duration = 300L
|
|
301
|
+
verify(animator).start()
|
|
302
|
+
|
|
303
|
+
val listenerCaptor = argumentCaptor<ValueAnimator.AnimatorUpdateListener>()
|
|
304
|
+
verify(animator).addUpdateListener(listenerCaptor.capture())
|
|
305
|
+
|
|
306
|
+
// Manually invoke the captured update listener, as TorchControllerTest
|
|
307
|
+
// does for its captured Runnable -- there's no real animation loop
|
|
308
|
+
// ticking a mocked ValueAnimator in a JVM unit test.
|
|
309
|
+
val tickingAnimator = mock<ValueAnimator> { on { getAnimatedValue() } doReturn 2.5f }
|
|
310
|
+
listenerCaptor.firstValue.onAnimationUpdate(tickingAnimator)
|
|
311
|
+
|
|
312
|
+
verify(camera.cameraControl).setZoomRatio(2.5f)
|
|
313
|
+
assertTrue(zoomEvents.contains(Triple(2.5f, 1.0f, 8.0f)))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@Test
|
|
317
|
+
fun `onAutoZoomSuggestion cancels a prior in-flight animator before starting a new one`() {
|
|
318
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
319
|
+
val controller = newController()
|
|
320
|
+
controller.attachCamera(camera)
|
|
321
|
+
|
|
322
|
+
valueAnimatorMock = mockStatic(ValueAnimator::class.java)
|
|
323
|
+
val firstAnimator = mock<ValueAnimator>()
|
|
324
|
+
val secondAnimator = mock<ValueAnimator>()
|
|
325
|
+
valueAnimatorMock.`when`<ValueAnimator> { ValueAnimator.ofFloat(any(), any()) }
|
|
326
|
+
.thenReturn(firstAnimator, secondAnimator)
|
|
327
|
+
|
|
328
|
+
controller.onAutoZoomSuggestion(4.0f)
|
|
329
|
+
controller.onAutoZoomSuggestion(4.0f) // commits firstAnimator
|
|
330
|
+
|
|
331
|
+
controller.onAutoZoomSuggestion(7.0f)
|
|
332
|
+
controller.onAutoZoomSuggestion(7.0f) // commits secondAnimator, should cancel firstAnimator first
|
|
333
|
+
|
|
334
|
+
verify(firstAnimator).cancel()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ============================================================
|
|
338
|
+
// cancelZoomAnimation
|
|
339
|
+
// ============================================================
|
|
340
|
+
|
|
341
|
+
@Test
|
|
342
|
+
fun `cancelZoomAnimation with no active animator does not throw`() {
|
|
343
|
+
val controller = newController()
|
|
344
|
+
|
|
345
|
+
controller.cancelZoomAnimation()
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
@Test
|
|
349
|
+
fun `cancelZoomAnimation cancels an in-flight animator and resets debounce state`() {
|
|
350
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
351
|
+
val controller = newController()
|
|
352
|
+
controller.attachCamera(camera)
|
|
353
|
+
|
|
354
|
+
valueAnimatorMock = mockStatic(ValueAnimator::class.java)
|
|
355
|
+
val animator = mock<ValueAnimator>()
|
|
356
|
+
valueAnimatorMock.`when`<ValueAnimator> { ValueAnimator.ofFloat(any(), any()) }.thenReturn(animator)
|
|
357
|
+
|
|
358
|
+
controller.onAutoZoomSuggestion(4.0f)
|
|
359
|
+
controller.onAutoZoomSuggestion(4.0f) // commits and starts `animator`
|
|
360
|
+
|
|
361
|
+
controller.cancelZoomAnimation()
|
|
362
|
+
|
|
363
|
+
verify(animator).cancel()
|
|
364
|
+
|
|
365
|
+
// Debounce state was reset -- a fresh suggestion needs two frames again.
|
|
366
|
+
val nextFirstFrame = controller.onAutoZoomSuggestion(4.0f)
|
|
367
|
+
assertFalse(nextFirstFrame)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
@Test
|
|
371
|
+
fun `detachCamera also cancels any in-flight zoom animation`() {
|
|
372
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 8.0f)
|
|
373
|
+
val controller = newController()
|
|
374
|
+
controller.attachCamera(camera)
|
|
375
|
+
|
|
376
|
+
valueAnimatorMock = mockStatic(ValueAnimator::class.java)
|
|
377
|
+
val animator = mock<ValueAnimator>()
|
|
378
|
+
valueAnimatorMock.`when`<ValueAnimator> { ValueAnimator.ofFloat(any(), any()) }.thenReturn(animator)
|
|
379
|
+
|
|
380
|
+
controller.onAutoZoomSuggestion(4.0f)
|
|
381
|
+
controller.onAutoZoomSuggestion(4.0f)
|
|
382
|
+
|
|
383
|
+
controller.detachCamera()
|
|
384
|
+
|
|
385
|
+
verify(animator).cancel()
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ============================================================
|
|
389
|
+
// currentMaxZoomRatio
|
|
390
|
+
// ============================================================
|
|
391
|
+
|
|
392
|
+
@Test
|
|
393
|
+
fun `currentMaxZoomRatio returns the default 8x when no camera is attached`() {
|
|
394
|
+
val controller = newController()
|
|
395
|
+
|
|
396
|
+
assertEquals(8.0f, controller.currentMaxZoomRatio(), 0.001f)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
@Test
|
|
400
|
+
fun `currentMaxZoomRatio returns the default 8x when zoomState value is null`() {
|
|
401
|
+
val zoomStateLiveData = mock<LiveData<ZoomState>>()
|
|
402
|
+
whenever(zoomStateLiveData.value).thenReturn(null)
|
|
403
|
+
val cameraInfo = mock<CameraInfo> {
|
|
404
|
+
on { getZoomState() } doReturn zoomStateLiveData
|
|
405
|
+
}
|
|
406
|
+
val camera = mock<Camera> { on { getCameraInfo() } doReturn cameraInfo }
|
|
407
|
+
val controller = newController()
|
|
408
|
+
controller.attachCamera(camera)
|
|
409
|
+
|
|
410
|
+
assertEquals(8.0f, controller.currentMaxZoomRatio(), 0.001f)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
@Test
|
|
414
|
+
fun `currentMaxZoomRatio returns the attached camera's maxZoomRatio`() {
|
|
415
|
+
val camera = mockCamera(zoomRatio = 1.0f, minZoom = 1.0f, maxZoom = 12.5f)
|
|
416
|
+
val controller = newController()
|
|
417
|
+
controller.attachCamera(camera)
|
|
418
|
+
|
|
419
|
+
assertEquals(12.5f, controller.currentMaxZoomRatio(), 0.001f)
|
|
420
|
+
}
|
|
421
|
+
}
|