import Path
import Version
@testable import Xcodes
import XCTest
class AppStateUpdateTests: XCTestCase {
var subject: AppState!
override func setUpWithError() throws {
Current = .mock
subject = AppState()
}
func testDoesNotReplaceInstallState() throws {
subject.allXcodes = [
Xcode(version: Version("0.0.0")!, installState: .installing(.unarchiving), selected: false, icon: nil)
]
subject.updateAllXcodes(
availableXcodes: [
AvailableXcode(version: Version("0.0.0")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil)
],
installedXcodes: [
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes[0].installState, .installing(.unarchiving))
}
func testRemovesUninstalledVersion() throws {
subject.allXcodes = [
Xcode(version: Version("0.0.0")!, installState: .installed(Path("/Applications/Xcode-0.0.0.app")!), selected: true, icon: NSImage(systemSymbolName: "app.fill", accessibilityDescription: nil))
]
subject.updateAllXcodes(
availableXcodes: [
AvailableXcode(version: Version("0.0.0")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil)
],
installedXcodes: [
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes[0].installState, .notInstalled)
}
func testDeterminesIfInstalledByBuildMetadataAlone() throws {
Current.defaults.string = { key in
if key == "dataSource" {
return "apple"
} else {
return nil
}
}
subject.allXcodes = [
]
subject.updateAllXcodes(
availableXcodes: [
// Note "GM" prerelease identifier
AvailableXcode(version: Version("0.0.0-GM+ABC123")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil)
],
installedXcodes: [
InstalledXcode(path: Path("/Applications/Xcode-0.0.0.app")!)!
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes[0].version, Version("0.0.0+ABC123")!)
XCTAssertEqual(subject.allXcodes[0].installState, .installed(Path("/Applications/Xcode-0.0.0.app")!))
XCTAssertEqual(subject.allXcodes[0].selected, false)
}
func testAdjustedVersionsAreUsedToLookupAvailableXcode() throws {
Current.defaults.string = { key in
if key == "dataSource" {
return "apple"
} else {
return nil
}
}
subject.allXcodes = [
]
subject.updateAllXcodes(
availableXcodes: [
// Note "GM" prerelease identifier
AvailableXcode(version: Version("0.0.0-GM+ABC123")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil, sdks: .init(iOS: .init("14.3")))
],
installedXcodes: [
InstalledXcode(path: Path("/Applications/Xcode-0.0.0.app")!)!
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes[0].version, Version("0.0.0+ABC123")!)
XCTAssertEqual(subject.allXcodes[0].installState, .installed(Path("/Applications/Xcode-0.0.0.app")!))
XCTAssertEqual(subject.allXcodes[0].selected, false)
// XCModel types aren't equatable, so just check for non-nil for now
XCTAssertNotNil(subject.allXcodes[0].sdks)
}
func testAppendingInstalledVersionThatIsNotAvailable() {
subject.allXcodes = [
]
subject.updateAllXcodes(
availableXcodes: [
AvailableXcode(version: Version("1.2.3")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil, sdks: .init(iOS: .init("14.3")))
],
installedXcodes: [
// There's a version installed which for some reason isn't listed online
InstalledXcode(path: Path("/Applications/Xcode-0.0.0.app")!)!
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes.map(\.version), [Version("1.2.3")!, Version("0.0.0+ABC123")!])
}
func testIdenticalBuilds_KeepsReleaseVersion_WithNeitherInstalled() {
Current.defaults.string = { key in
if key == "dataSource" {
return "xcodeReleases"
} else {
return nil
}
}
subject.allXcodes = [
]
subject.updateAllXcodes(
availableXcodes: [
AvailableXcode(version: Version("12.4.0+12D4e")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil),
AvailableXcode(version: Version("12.4.0-RC+12D4e")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil),
],
installedXcodes: [
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes.map(\.version), [Version("12.4.0+12D4e")!])
XCTAssertEqual(subject.allXcodes.map(\.identicalBuilds), [[Version("12.4.0+12D4e")!, Version("12.4.0-RC+12D4e")!]])
}
func testIdenticalBuilds_KeepsReleaseVersion_WithPrereleaseInstalled() {
Current.defaults.string = { key in
if key == "dataSource" {
return "xcodeReleases"
} else {
return nil
}
}
subject.allXcodes = [
]
Current.files.contentsAtPath = { path in
if path.contains("Info.plist") {
return """
CFBundleIdentifier
com.apple.dt.Xcode
CFBundleShortVersionString
12.4.0
""".data(using: .utf8)
}
else if path.contains("version.plist") {
return """
ProductBuildVersion
12D4e
""".data(using: .utf8)
}
else {
return nil
}
}
subject.updateAllXcodes(
availableXcodes: [
AvailableXcode(version: Version("12.4.0+12D4e")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil),
AvailableXcode(version: Version("12.4.0-RC+12D4e")!, url: URL(string: "https://apple.com/xcode.xip")!, filename: "mock.xip", releaseDate: nil),
],
installedXcodes: [
InstalledXcode(path: Path("/Applications/Xcode-12.4.0-RC.app")!)!
],
selectedXcodePath: nil
)
XCTAssertEqual(subject.allXcodes.map(\.version), [Version("12.4.0+12D4e")!])
XCTAssertEqual(subject.allXcodes.map(\.identicalBuilds), [[Version("12.4.0+12D4e")!, Version("12.4.0-RC+12D4e")!]])
}
}