mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-22 18:31:12 +00:00
* 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
64 lines
2.4 KiB
Swift
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")
|
|
}
|
|
}
|