Visitar URL original
Move the hotspot lifecycle into a tested HotspotSession by viktor-svirsky · Pull Request #25 · viktor-svirsky/tether · GitHub
Skip to content

Move the hotspot lifecycle into a tested HotspotSession - #25

Closed
viktor-svirsky wants to merge 2 commits into
mainfrom
model-lifecycle-tests
Closed

viktor-svirsky wants to merge 2 commits into
mainfrom
model-lifecycle-tests

Conversation

@viktor-svirsky

Copy link
Copy Markdown
Owner

The hotspot lifecycle moves out of Model into HotspotSession, a Foundation-only type in TetherCore, so swift test covers it. It takes the saved devices, the server, the keep-alive sound, the hotspot lookup and the clock as inputs. WireGuardServer conforms to a small WireGuardServing protocol, KeepAlive to KeepAliveSound.

Model stays what SwiftUI observes. It keeps the watcher, the sampler, the scene observers and the demo hooks, and forwards the rest. The session calls willChange before each change it publishes, the way @Published does, and Model sends objectWillChange from it. So the screen redraws as before, and a demo launch can still set running and the rest directly.

Interfaces moves along, with the hotspot filter split from getifaddrs so it has its own test.

This is a refactor: no behaviour change, and the existing unit and UI tests are unchanged. The Phase and WireGuardProblem enums from the issue are left out: the views and Shortcuts read running and the problem text, so the enums would only add a mapping back to the same strings.

New tests (21, in Tests/HotspotSessionTests.swift), most of them tables of watcher rounds: the server following the hotspot on, off and to a new address, locked keys then unlocked, a start that fails and is tried again each round, a start error going with the hotspot, the setup problem showing first, a problem logged once, the restart when the server refuses a device list (and a restart that fails), the 10-minute wait on and off screen and after opening Tether, claiming the ready device in the background and on screen, what the Shortcuts actions read, the speeds, each change announced before it happens, and the hotspot address filter.

Tested:

  • scripts/build-wireguard.sh && swift test: 94 tests, 0 failures, 6 Keychain tests skipped as before. The first commit alone: 73, 0 failures.
  • A deliberate break in each of four places (the on-screen wait, the start error clearing, the background claim, a missing willSet) fails the new tests.
  • Simulator app build.
  • Full UI suite, 51 tests, 0 failures, on iOS 27.0 (iPhone 17 Pro) and iOS 18.5 (iPhone SE (3rd generation)).

Fixes #14

Model.swift isn't in TetherCore and needs UIKit, so the logic that
starts and stops the server with the hotspot had no unit test. It now
lives in HotspotSession, Foundation only, which takes the saved
devices, the server, the keep-alive sound, the hotspot lookup and the
clock as inputs. WireGuardServer and KeepAlive conform to two small
protocols for that.

Model keeps the timers, the scene observers and the demo hooks, and
forwards the rest. The session announces each change before it
happens, as @published does, so the screen redraws as before, and a
demo launch can still set the state the UI tests expect.

Interfaces moves along, with the hotspot filter split from getifaddrs
so it can be tested on its own.
Table tests with a fake server, sound, hotspot and clock: the server
following the hotspot on, off and to a new address, locked keys then
unlocked, a start that fails and is tried again each round, a start
error going with the hotspot, the setup problem showing first, the
restart when the server refuses a device list, the 10-minute wait on
and off screen, claiming the ready device in the background, the
speeds, and the hotspot address filter.

Fixes #14
Copilot AI balanced review requested due to automatic review settings October 30, 2026 02:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The hotspot lifecycle extraction has no active review issues.

No open issues 🎉

What changed in this PR

Extracts the hotspot lifecycle from Model into a Foundation-only HotspotSession, making the logic testable through TetherCore and addressing #14 while preserving the existing UI-facing API.

Changes:

  • Moves lifecycle decisions into a session with injected server, keep-alive sound, hotspot lookup, and clock.
  • Keeps timers, scene observers, demo hooks, and SwiftUI notifications in Model.
  • Adds 21 tests covering hotspot transitions, retries, device claiming, keep-alive timing, speeds, notifications, and address filtering.
File Description
Tests/​HotspotSessionTests.swift Adds lifecycle tests using fake dependencies and a controlled clock.
Sources/​Model.swift Delegates lifecycle behavior to the session while retaining app integration.
Sources/​HotspotSession.swift Introduces the testable lifecycle, dependency protocols, and extracted interface filter.
Package.swift Includes HotspotSession.swift in TetherCore.

Review effort: Balanced

@viktor-svirsky

Copy link
Copy Markdown
Owner Author

Merged to main as 6edaac6..fb0f607, rebased onto 027d2fc, plus a commit updating README, TESTING.md and a comment that still named Model.

@viktor-svirsky
viktor-svirsky deleted the model-lifecycle-tests branch October 30, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Test the hotspot lifecycle in Model

2 participants