Files
ggbond268--mactools/Tests/Core/Plugins/Dynamic/PluginPackageManifestTests.swift
wehub-resource-sync 1d1286fadb
Build / Build and test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:18:38 +08:00

182 lines
6.4 KiB
Swift

import XCTest
@testable import MacTools
final class PluginPackageManifestTests: XCTestCase {
func testManifestValidationAcceptsCurrentPackageFormat() throws {
let manifest = PluginPackageManifest(
id: "com.example.demo",
displayName: "Demo",
version: "1.0.0",
minHostVersion: "0.15.0",
bundleRelativePath: "Demo.bundle",
capabilities: .init(primaryPanel: true)
)
XCTAssertNoThrow(try PluginPackageManifestLoader.validate(manifest, hostVersion: "0.16.0"))
}
func testManifestValidationRejectsPreviousPluginKitVersion() {
let manifest = PluginPackageManifest(
id: "com.example.demo",
displayName: "Demo",
version: "1.0.0",
minHostVersion: "0.15.0",
pluginKitVersion: 1,
bundleRelativePath: "Demo.bundle"
)
XCTAssertThrowsError(try PluginPackageManifestLoader.validate(manifest, hostVersion: "0.16.0")) { error in
XCTAssertEqual(error as? PluginPackageManifestError, .unsupportedPluginKitVersion(1))
}
}
func testManifestValidationRejectsUnsafeBundlePath() {
let manifest = PluginPackageManifest(
id: "com.example.demo",
displayName: "Demo",
version: "1.0.0",
minHostVersion: "0.15.0",
bundleRelativePath: "../Demo.bundle"
)
XCTAssertThrowsError(try PluginPackageManifestLoader.validate(manifest, hostVersion: "0.16.0")) { error in
XCTAssertEqual(error as? PluginPackageManifestError, .invalidBundleRelativePath("../Demo.bundle"))
}
}
func testManifestValidationRejectsInvalidVersion() {
let manifest = PluginPackageManifest(
id: "com.example.demo",
displayName: "Demo",
version: "1.0-beta",
minHostVersion: "0.15.0",
bundleRelativePath: "Demo.bundle"
)
XCTAssertThrowsError(try PluginPackageManifestLoader.validate(manifest, hostVersion: "0.16.0")) { error in
XCTAssertEqual(error as? PluginPackageManifestError, .invalidVersion("1.0-beta"))
}
}
func testManifestValidationRejectsIncompatibleHostVersion() {
let manifest = PluginPackageManifest(
id: "com.example.demo",
displayName: "Demo",
version: "1.0.0",
minHostVersion: "1.0.0",
bundleRelativePath: "Demo.bundle"
)
XCTAssertThrowsError(try PluginPackageManifestLoader.validate(manifest, hostVersion: "0.16.0")) { error in
XCTAssertEqual(
error as? PluginPackageManifestError,
.incompatibleHostVersion(required: "1.0.0", current: "0.16.0")
)
}
}
func testManifestDecodesWithCategoryAndReleaseChannel() throws {
let json = """
{
"id": "demo",
"displayName": "Demo",
"version": "1.0.0",
"minHostVersion": "0.15.0",
"pluginKitVersion": 1,
"bundleRelativePath": "Demo.bundle",
"capabilities": { "primaryPanel": true, "componentPanel": false, "configuration": false },
"permissions": [],
"category": "display",
"releaseChannel": "beta",
"localizedMetadata": {
"en": {
"displayName": "Demo",
"summary": "Demo plugin"
},
"zh-Hans": {
"displayName": "示例",
"summary": "示例插件"
}
}
}
""".data(using: .utf8)!
let manifest = try JSONDecoder().decode(PluginPackageManifest.self, from: json)
XCTAssertEqual(manifest.category, "display")
XCTAssertEqual(manifest.releaseChannel, "beta")
XCTAssertEqual(manifest.localizedMetadata?["en"]?.summary, "Demo plugin")
}
func testManifestDecodesWithoutCategoryAndReleaseChannelGracefully() throws {
// Legacy plugin.json files without category/releaseChannel should still decode.
let json = """
{
"id": "demo",
"displayName": "Demo",
"version": "1.0.0",
"minHostVersion": "0.15.0",
"pluginKitVersion": 1,
"bundleRelativePath": "Demo.bundle",
"capabilities": { "primaryPanel": true, "componentPanel": false, "configuration": false },
"permissions": []
}
""".data(using: .utf8)!
let manifest = try JSONDecoder().decode(PluginPackageManifest.self, from: json)
XCTAssertNil(manifest.category)
XCTAssertNil(manifest.releaseChannel)
}
func testLocalizedMetadataMatchesPreferredLanguageAndFallbacks() {
let metadata = [
"en": PluginLocalizedMetadata(displayName: "Calendar", summary: "Events"),
"zh-Hans": PluginLocalizedMetadata(displayName: "日历", summary: "日程"),
"zh-Hant": PluginLocalizedMetadata(displayName: "行事曆", summary: "事件")
]
XCTAssertEqual(
PluginLocalizationMatcher.localizedMetadata(
from: metadata,
preferredLanguages: ["en-US"]
)?.displayName,
"Calendar"
)
XCTAssertEqual(
PluginLocalizationMatcher.localizedMetadata(
from: metadata,
preferredLanguages: ["zh-HK"]
)?.displayName,
"行事曆"
)
XCTAssertEqual(
PluginLocalizationMatcher.localizedMetadata(
from: metadata,
preferredLanguages: ["fr-FR"]
)?.displayName,
"Calendar"
)
}
func testLocalizedMetadataUsesAppleLanguagesOverrideBeforeSystemLanguages() throws {
let metadata = [
"en": PluginLocalizedMetadata(displayName: "Calendar", summary: "Events"),
"zh-Hans": PluginLocalizedMetadata(displayName: "日历", summary: "日程")
]
let suiteName = "PluginLocalizationMatcherTests.\(UUID().uuidString)"
let userDefaults = try XCTUnwrap(UserDefaults(suiteName: suiteName))
defer {
userDefaults.removePersistentDomain(forName: suiteName)
}
userDefaults.set(["en"], forKey: "AppleLanguages")
XCTAssertEqual(
PluginLocalizationMatcher.localizedMetadata(
from: metadata,
userDefaults: userDefaults
)?.displayName,
"Calendar"
)
}
}