Files
openclaw/apps/ios/Tests/AgentOverviewRefreshGateTests.swift
Peter Steinberger 334e7f3f21 feat(apps): add native mobile Automations parity (#106355)
* fix(apps): address native Skills review feedback

* feat(apps): add native Automations parity

* fix(ios): preserve automation editor selection

* fix(android): page automation discovery

* chore(apps): refresh native source inventory

* fix(ios): refresh invalid automation diagnostics

* chore(apps): sync native localization

* fix(cron): stabilize paginated snapshots

* refactor(cron): split pagination helpers

* fix(apps): address final native review feedback

* chore(apps): refresh native source inventory

* fix(ios): dedupe automation list actions

* chore: keep release note in PR context

* fix(ci): repair current main architecture gates

* fix(ios): default new skill requirement fields

* fix(ios): retain queued automation reservations
2026-07-13 15:35:32 -07:00

64 lines
2.4 KiB
Swift

import Foundation
import Testing
@testable import OpenClaw
struct AgentOverviewRefreshGateTests {
@Test func `legacy skill missing requirements default new fields`() throws {
let report = try JSONDecoder().decode(
SkillStatusReportLite.self,
from: Data(#"{"skills":[{"name":"Legacy","missing":{"bins":[],"env":[],"config":[]}}]}"#.utf8))
let skill = try #require(report.skills.first)
#expect(skill.missing?.anyBins == [])
#expect(skill.missing?.os == [])
#expect(!skill.hasMissingRequirements)
}
@Test func `any binary requirements participate in skill setup state`() throws {
let report = try JSONDecoder().decode(
SkillStatusReportLite.self,
from: Data(
#"{"skills":[{"name":"Search","missing":{"bins":[],"anyBins":["rg","grep"],"env":[],"config":[],"os":[]}}]}"#
.utf8))
let skill = try #require(report.skills.first)
#expect(skill.hasMissingRequirements)
#expect(skill.missingSummary == "rg, grep")
#expect(skill.missingBins == ["rg", "grep"])
}
@Test func `new overview refresh invalidates an older result`() {
var gate = AgentOverviewRefreshGate()
let first = gate.begin()
let second = gate.begin()
#expect(!gate.isCurrent(first))
#expect(gate.isCurrent(second))
}
@Test func `current overview refresh remains accepted until superseded`() {
var gate = AgentOverviewRefreshGate()
let generation = gate.begin()
#expect(gate.isCurrent(generation))
}
@Test func `automatic refresh coalesces before invalidating current work`() throws {
let source = try String(contentsOf: Self.gatewayDataSourceURL(), encoding: .utf8)
let method = try #require(source.range(of: "func refreshOverview(force: Bool) async"))
let tail = source[method.lowerBound...]
let coalescingGuard = try #require(tail.range(of: "if self.overviewLoading, !force"))
let generation = try #require(tail.range(of: "let generation = self.overviewRefreshGate.begin()"))
#expect(coalescingGuard.lowerBound < generation.lowerBound)
}
private static func gatewayDataSourceURL() -> URL {
URL(fileURLWithPath: #filePath)
.deletingLastPathComponent()
.deletingLastPathComponent()
.appendingPathComponent("Sources/Design/AgentProTab+GatewayData.swift")
}
}