fix: show a generic "App Blocked" shield instead of mis-attributing a rule
The shield titled itself with the first enabled rule whose selection contained the app, regardless of whether that rule was the one actually blocking. When several rules covered the same app (e.g. a dormant schedule + the active limit) it named the wrong rule. Drop the rule-name lookup entirely: every shield now carries a generic "App Blocked" title. Open-limit shields keep their functional detail (running count + "Open (N left)" button) beneath that title. The text-only decision moves into a pure, unit-tested ShieldPresentation in Shared/, and the now-dead ShieldLookup.snapshot(containingApplication:) is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
53
OpenAppLockTests/ShieldPresentationTests.swift
Normal file
53
OpenAppLockTests/ShieldPresentationTests.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// ShieldPresentationTests.swift
|
||||
// OpenAppLockTests
|
||||
//
|
||||
|
||||
import Testing
|
||||
|
||||
@testable import OpenAppLock
|
||||
|
||||
@Suite("Shield presentation")
|
||||
struct ShieldPresentationTests {
|
||||
@Test("Fully-blocked shield is generic and names no rule")
|
||||
func blockedIsGeneric() {
|
||||
let presentation = ShieldPresentation.blocked
|
||||
#expect(presentation.title == "App Blocked")
|
||||
#expect(presentation.subtitle == "This app is blocked by OpenAppLock.")
|
||||
#expect(presentation.secondaryButton == nil)
|
||||
}
|
||||
|
||||
@Test("Open-limit shield with opens remaining shows counts and an Open button")
|
||||
func openLimitWithOpensRemaining() {
|
||||
let presentation = ShieldPresentation.openLimit(
|
||||
opensUsed: 2, maxOpens: 5, sessionMinutes: 15)
|
||||
// Title is generic — never the rule name.
|
||||
#expect(presentation.title == "App Blocked")
|
||||
#expect(presentation.subtitle.contains("Opened 2 of 5 times today"))
|
||||
#expect(presentation.subtitle.contains("15 minutes"))
|
||||
#expect(presentation.secondaryButton == "Open (3 left)")
|
||||
}
|
||||
|
||||
@Test("A single remaining open reads in the singular")
|
||||
func openLimitSingularRemaining() {
|
||||
let presentation = ShieldPresentation.openLimit(
|
||||
opensUsed: 4, maxOpens: 5, sessionMinutes: 15)
|
||||
#expect(presentation.secondaryButton == "Open (1 left)")
|
||||
}
|
||||
|
||||
@Test("Spent open-limit shield drops the Open button and reads as blocked")
|
||||
func openLimitExhausted() {
|
||||
let presentation = ShieldPresentation.openLimit(
|
||||
opensUsed: 5, maxOpens: 5, sessionMinutes: 15)
|
||||
#expect(presentation.title == "App Blocked")
|
||||
#expect(presentation.subtitle == "No opens left today — the block lifts tomorrow.")
|
||||
#expect(presentation.secondaryButton == nil)
|
||||
}
|
||||
|
||||
@Test("Over-spending never yields a negative or non-nil Open button")
|
||||
func openLimitOverSpent() {
|
||||
let presentation = ShieldPresentation.openLimit(
|
||||
opensUsed: 9, maxOpens: 5, sessionMinutes: 15)
|
||||
#expect(presentation.secondaryButton == nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user