Redline: OneDrive folder transport as alternative to AirDrop (MMDB-2631) #23
@@ -17,6 +17,15 @@ public actor ReturnWatcher {
|
||||
/// A document that IS commented is always recorded, regardless of this flag.
|
||||
public var recordUncommented: Bool = true
|
||||
|
||||
/// The folder this watcher is CURRENTLY seeded to scan/watch — whatever `init`
|
||||
/// last set it to, or `updateWatchFolder` since. Exposed so tests can observe the
|
||||
/// watcher's seeded folder directly (e.g. right after construction, before
|
||||
/// `start()`/`updateWatchFolder()` ever run) rather than only inferring it
|
||||
/// indirectly through `scanNow()`'s behavior.
|
||||
public var currentWatchFolder: URL {
|
||||
watchFolder
|
||||
}
|
||||
|
||||
/// Watch folder is `paths.watchFolder`, which production constructs from
|
||||
/// `FolderSettings.resolve().watch`. This type never calls FolderSettings;
|
||||
/// `updateWatchFolder` is invoked by the UI layer only.
|
||||
|
||||
@@ -5,14 +5,26 @@ import Testing
|
||||
import ShotdeckCore
|
||||
@testable import Shotdeck
|
||||
|
||||
/// Coverage gap closed (adversarial review, round 3): the Core-level regression tests
|
||||
/// in ShotdeckCoreTests hand-replicate what `AppDelegate.makeLaunchModel()` and
|
||||
/// Coverage gap closed (adversarial review, rounds 3 and 4): the Core-level regression
|
||||
/// tests in ShotdeckCoreTests hand-replicate what `AppDelegate.makeLaunchModel()` and
|
||||
/// `AppModel.bootstrap()` do, rather than calling them — so a future revert of
|
||||
/// `makeLaunchModel()` back to the AirDrop-only resolver, or a dropped
|
||||
/// `updateWatchFolder` call inside `bootstrap()`, would NOT fail `swift test`. This
|
||||
/// test goes through the real, unmodified call sites in the `Shotdeck` executable
|
||||
/// target via `@testable import`, which `ShotdeckCoreTests` cannot reach (it only
|
||||
/// depends on `ShotdeckCore`) — hence this separate `ShotdeckTests` target.
|
||||
///
|
||||
/// Round 4 correction: the first version of this test asserted only
|
||||
/// `model.watchFolderURL`, which `AppModel.init` computes independently via
|
||||
/// `TransportSettings.effectiveFolders()` — so it stayed correct (and the test kept
|
||||
/// passing) even when `makeLaunchModel()` was reverted to the AirDrop-only resolver,
|
||||
/// because `bootstrap()`'s own unconditional `updateWatchFolder` reconcile papered
|
||||
/// over the reverted resolver. That made the "verified this catches the blocker"
|
||||
/// claim in the previous round's commit message empirically false. This version
|
||||
/// asserts `model.paths`/the watcher's `currentWatchFolder` BEFORE `bootstrap()` runs,
|
||||
/// which actually depends on what `makeLaunchModel()` built — see this file's git
|
||||
/// history (or the round-4 commit message) for the verbatim before/after
|
||||
/// `swift test --filter` output proving it now discriminates correctly.
|
||||
@MainActor
|
||||
@Test("Real wiring: AppDelegate.makeLaunchModel() + AppModel.bootstrap() detect a marked OneDrive return")
|
||||
func realLaunchModelAndBootstrapDetectAMarkedOneDriveReturn() async throws {
|
||||
@@ -73,6 +85,22 @@ func realLaunchModelAndBootstrapDetectAMarkedOneDriveReturn() async throws {
|
||||
// combo already taken / the global hotkey table in an unexpected state.
|
||||
defer { model.hotkeys.unregisterAll() }
|
||||
|
||||
// PRE-bootstrap assertions — this is the actual proof of the launch RESOLVER
|
||||
// (AppDelegate.makeLaunchModel() -> TransportSettings.resolvedAppSupportPaths()),
|
||||
// independent of bootstrap()'s own reconcile. `model.watchFolderURL` alone does
|
||||
// NOT prove this: AppModel.init computes it separately via
|
||||
// TransportSettings.effectiveFolders(), so it would read as correct even if
|
||||
// makeLaunchModel's `paths` were built by the AirDrop-only resolver — which is
|
||||
// exactly how the first version of this test was empirically shown to be vacuous
|
||||
// for the launch-resolver path (see this commit's message). `model.paths` is
|
||||
// `internal` on AppModel, so @testable import already exposes it without any
|
||||
// production API change; `currentWatchFolder` is the one new (internal-facing,
|
||||
// `public` on the actor) seam added to ReturnWatcher for this purpose.
|
||||
#expect(model.paths.watchFolder.path == oneDriveFolder.path)
|
||||
#expect(model.paths.outbox.path == oneDriveFolder.path)
|
||||
let seededWatchFolder = await model.watcher.currentWatchFolder
|
||||
#expect(seededWatchFolder.path == oneDriveFolder.path)
|
||||
|
||||
#expect(model.transport == .oneDrive)
|
||||
#expect(model.watchFolderURL.path == oneDriveFolder.path)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user