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.
|
/// A document that IS commented is always recorded, regardless of this flag.
|
||||||
public var recordUncommented: Bool = true
|
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
|
/// Watch folder is `paths.watchFolder`, which production constructs from
|
||||||
/// `FolderSettings.resolve().watch`. This type never calls FolderSettings;
|
/// `FolderSettings.resolve().watch`. This type never calls FolderSettings;
|
||||||
/// `updateWatchFolder` is invoked by the UI layer only.
|
/// `updateWatchFolder` is invoked by the UI layer only.
|
||||||
|
|||||||
@@ -5,14 +5,26 @@ import Testing
|
|||||||
import ShotdeckCore
|
import ShotdeckCore
|
||||||
@testable import Shotdeck
|
@testable import Shotdeck
|
||||||
|
|
||||||
/// Coverage gap closed (adversarial review, round 3): the Core-level regression tests
|
/// Coverage gap closed (adversarial review, rounds 3 and 4): the Core-level regression
|
||||||
/// in ShotdeckCoreTests hand-replicate what `AppDelegate.makeLaunchModel()` and
|
/// tests in ShotdeckCoreTests hand-replicate what `AppDelegate.makeLaunchModel()` and
|
||||||
/// `AppModel.bootstrap()` do, rather than calling them — so a future revert of
|
/// `AppModel.bootstrap()` do, rather than calling them — so a future revert of
|
||||||
/// `makeLaunchModel()` back to the AirDrop-only resolver, or a dropped
|
/// `makeLaunchModel()` back to the AirDrop-only resolver, or a dropped
|
||||||
/// `updateWatchFolder` call inside `bootstrap()`, would NOT fail `swift test`. This
|
/// `updateWatchFolder` call inside `bootstrap()`, would NOT fail `swift test`. This
|
||||||
/// test goes through the real, unmodified call sites in the `Shotdeck` executable
|
/// test goes through the real, unmodified call sites in the `Shotdeck` executable
|
||||||
/// target via `@testable import`, which `ShotdeckCoreTests` cannot reach (it only
|
/// target via `@testable import`, which `ShotdeckCoreTests` cannot reach (it only
|
||||||
/// depends on `ShotdeckCore`) — hence this separate `ShotdeckTests` target.
|
/// 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
|
@MainActor
|
||||||
@Test("Real wiring: AppDelegate.makeLaunchModel() + AppModel.bootstrap() detect a marked OneDrive return")
|
@Test("Real wiring: AppDelegate.makeLaunchModel() + AppModel.bootstrap() detect a marked OneDrive return")
|
||||||
func realLaunchModelAndBootstrapDetectAMarkedOneDriveReturn() async throws {
|
func realLaunchModelAndBootstrapDetectAMarkedOneDriveReturn() async throws {
|
||||||
@@ -73,6 +85,22 @@ func realLaunchModelAndBootstrapDetectAMarkedOneDriveReturn() async throws {
|
|||||||
// combo already taken / the global hotkey table in an unexpected state.
|
// combo already taken / the global hotkey table in an unexpected state.
|
||||||
defer { model.hotkeys.unregisterAll() }
|
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.transport == .oneDrive)
|
||||||
#expect(model.watchFolderURL.path == oneDriveFolder.path)
|
#expect(model.watchFolderURL.path == oneDriveFolder.path)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user