From a7b9ea7d0a692de738fdd58c41b679bf762569d5 Mon Sep 17 00:00:00 2001 From: David Martinez Date: Fri, 3 Oct 2025 12:07:22 +0200 Subject: [PATCH 01/15] feat: add iPhone 17 support --- Sources/DeviceIdentificator/Models/IPhoneModel+Name.swift | 4 ++++ Sources/DeviceIdentificator/Models/IPhoneModel.swift | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Sources/DeviceIdentificator/Models/IPhoneModel+Name.swift b/Sources/DeviceIdentificator/Models/IPhoneModel+Name.swift index 8eea7e9..b740e55 100644 --- a/Sources/DeviceIdentificator/Models/IPhoneModel+Name.swift +++ b/Sources/DeviceIdentificator/Models/IPhoneModel+Name.swift @@ -60,6 +60,10 @@ public extension DeviceModel.IPhoneModel { case .iPhone16Pro: return "iPhone 16 Pro" case .iPhone16ProMax: return "iPhone 16 Pro Max" case .iPhone16e: return "iPhone 16e" + case .iPhone17: return "iPhone 17" + case .iPhone17Pro: return "iPhone 17 Pro" + case .iPhone17ProMax: return "iPhone 17 Pro Max" + case .iPhoneAir: return "iPhone Air" } } } diff --git a/Sources/DeviceIdentificator/Models/IPhoneModel.swift b/Sources/DeviceIdentificator/Models/IPhoneModel.swift index 22daa01..246a733 100644 --- a/Sources/DeviceIdentificator/Models/IPhoneModel.swift +++ b/Sources/DeviceIdentificator/Models/IPhoneModel.swift @@ -59,5 +59,9 @@ public extension DeviceModel { case iPhone16Pro = "iPhone17,1" case iPhone16ProMax = "iPhone17,2" case iPhone16e = "iPhone17,5" + case iPhone17 = "iPhone18,3" + case iPhone17Pro = "iPhone18,1" + case iPhone17ProMax = "iPhone18,2" + case iPhoneAir = "iPhone18,4" } } From ab9fd80d8f320ddf82b8fa1524c3d60f31d2b95e Mon Sep 17 00:00:00 2001 From: David Martinez Date: Fri, 3 Oct 2025 12:38:42 +0200 Subject: [PATCH 02/15] feat: new devices --- .../DeviceIdentificator/DeviceModel+Capabilities.swift | 4 +--- .../Models/AppleWatchModel+Name.swift | 9 +++++++++ .../DeviceIdentificator/Models/AppleWatchModel.swift | 9 +++++++++ .../DeviceIdentificator/Models/IPadModel+Name.swift | 10 ++++++++-- Sources/DeviceIdentificator/Models/IPadModel.swift | 10 ++++++++-- .../Models/IPhoneModel+Processor.swift | 4 ++++ Sources/DeviceIdentificator/Processor.swift | 2 ++ 7 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Sources/DeviceIdentificator/DeviceModel+Capabilities.swift b/Sources/DeviceIdentificator/DeviceModel+Capabilities.swift index f9afa65..1d3288e 100644 --- a/Sources/DeviceIdentificator/DeviceModel+Capabilities.swift +++ b/Sources/DeviceIdentificator/DeviceModel+Capabilities.swift @@ -46,8 +46,6 @@ public extension DeviceModel { .iPad(.air13InchM2Cellular), .iPad(.mini6Wifi), .iPad(.mini6Cellular), - .iPad(.mini7Wifi), - .iPad(.mini7Cellular), .iPad(.pro1_11inchWifi), .iPad(.pro1_11inchWifiTera), .iPad(.pro1_11inchCellular), @@ -135,4 +133,4 @@ public extension DeviceModel { return false } } -} \ No newline at end of file +} diff --git a/Sources/DeviceIdentificator/Models/AppleWatchModel+Name.swift b/Sources/DeviceIdentificator/Models/AppleWatchModel+Name.swift index 7f46dc5..0a0ace7 100644 --- a/Sources/DeviceIdentificator/Models/AppleWatchModel+Name.swift +++ b/Sources/DeviceIdentificator/Models/AppleWatchModel+Name.swift @@ -47,6 +47,15 @@ public extension DeviceModel.AppleWatchModel { case .SE2_44mmCellular: return "Apple Watch SE2 44mm" case .ultra: return "Apple Watch Ultra 1" case .ultra2: return "Apple Watch Ultra 2" + case .series10_42mmGPS: return "Apple Watch Series 10 42mm" + case .series10_46mmGPS: return "Apple Watch Series 10 46mm" + case .series10_42mmCellular: return "Apple Watch Series 10 42mm" + case .series10_46mmCellular: return "Apple Watch Series 10 46mm" + case .ultra3: return "Apple Watch Ultra 3" + case .series11_42mmGPS: return "Apple Watch Series 11 42mm" + case .series11_46mmGPS: return "Apple Watch Series 11 46mm" + case .series11_42mmCellular: return "Apple Watch Series 11 42mm" + case .series11_46mmCellular: return "Apple Watch Series 11 46mm" } } } diff --git a/Sources/DeviceIdentificator/Models/AppleWatchModel.swift b/Sources/DeviceIdentificator/Models/AppleWatchModel.swift index ebca557..33ca2c4 100644 --- a/Sources/DeviceIdentificator/Models/AppleWatchModel.swift +++ b/Sources/DeviceIdentificator/Models/AppleWatchModel.swift @@ -46,5 +46,14 @@ public extension DeviceModel { case series9_41mmCellular = "Watch7,3" case series9_45mmCellular = "Watch7,4" case ultra2 = "Watch7,5" + case series10_42mmGPS = "Watch7,8" + case series10_46mmGPS = "Watch7,9" + case series10_42mmCellular = "Watch7,10" + case series10_46mmCellular = "Watch7,11" + case ultra3 = "Watch7,12" + case series11_42mmGPS = "Watch7,17" + case series11_46mmGPS = "Watch7,18" + case series11_42mmCellular = "Watch7,19" + case series11_46mmCellular = "Watch7,20" } } diff --git a/Sources/DeviceIdentificator/Models/IPadModel+Name.swift b/Sources/DeviceIdentificator/Models/IPadModel+Name.swift index 3bd68e7..2d65615 100644 --- a/Sources/DeviceIdentificator/Models/IPadModel+Name.swift +++ b/Sources/DeviceIdentificator/Models/IPadModel+Name.swift @@ -28,6 +28,8 @@ public extension DeviceModel.IPadModel { case .gen9Cellular: return "iPad 9G (Cellular)" case .gen10Wifi: return "iPad 10G (Wifi)" case .gen10Cellular: return "iPad 10G (Cellular)" + case .gen11Wifi: return "iPad 11G (Wifi)" + case .gen11Cellular: return "iPad 11G (Cellular)" // Minis case .mini1Wifi: return "iPad Mini 1 (Wifi)" @@ -45,8 +47,8 @@ public extension DeviceModel.IPadModel { case .mini5Cellular: return "iPad Mini 5 (Cellular)" case .mini6Wifi: return "iPad Mini 6 (Wifi)" case .mini6Cellular: return "iPad Mini 6 (Cellular)" - case .mini7Wifi: return "iPad Mini 7 (Wifi)" - case .mini7Cellular: return "iPad Mini 7 (Cellular)" + case .miniA17ProWifi: return "iPad Mini A17 Pro (Wifi)" + case .miniA17ProCellular: return "iPad Mini A17 Pro (Cellular)" // Airs case .air1Wifi: return "iPad Air 1 (Wifi)" @@ -64,6 +66,10 @@ public extension DeviceModel.IPadModel { case .air11InchM2Cellular: return "iPad Air M2 11\" (Cellular)" case .air13InchM2Wifi: return "iPad Air M2 13\" (Cellular)" case .air13InchM2Cellular: return "iPad Air M2 13\" (Cellular)" + case .air11InchM3Wifi: return "iPad Air M3 11\" (Wifi)" + case .air11InchM3Cellular: return "iPad Air M3 11\" (Cellular)" + case .air13InchM3Wifi: return "iPad Air M3 13\" (Wifi)" + case .air13InchM3Cellular: return "iPad Air M3 13\" (Cellular)" // Pros case .pro1_9d7inchWifi: return "iPad Pro 1G 9.7\" (Wifi)" diff --git a/Sources/DeviceIdentificator/Models/IPadModel.swift b/Sources/DeviceIdentificator/Models/IPadModel.swift index bfc905f..4da8c53 100644 --- a/Sources/DeviceIdentificator/Models/IPadModel.swift +++ b/Sources/DeviceIdentificator/Models/IPadModel.swift @@ -27,6 +27,8 @@ public extension DeviceModel { case gen9Cellular = "iPad12,2" case gen10Wifi = "iPad13,18" case gen10Cellular = "iPad13,19" + case gen11Wifi = "iPad15,7" + case gen11Cellular = "iPad15,8" // Minis case mini1Wifi = "iPad2,5" @@ -44,8 +46,8 @@ public extension DeviceModel { case mini5Cellular = "iPad11,2" case mini6Wifi = "iPad14,1" case mini6Cellular = "iPad14,2" - case mini7Wifi = "iPad16,1" - case mini7Cellular = "iPad16,2" + case miniA17ProWifi = "iPad16,1" + case miniA17ProCellular = "iPad16,2" // Airs case air1Wifi = "iPad4,1" @@ -63,6 +65,10 @@ public extension DeviceModel { case air11InchM2Cellular = "iPad14,9" case air13InchM2Wifi = "iPad14,10" case air13InchM2Cellular = "iPad14,11" + case air11InchM3Wifi = "iPad15,3" + case air11InchM3Cellular = "iPad15,4" + case air13InchM3Wifi = "iPad15,5" + case air13InchM3Cellular = "iPad15,6" // Pros case pro1_9d7inchWifi = "iPad6,3" diff --git a/Sources/DeviceIdentificator/Models/IPhoneModel+Processor.swift b/Sources/DeviceIdentificator/Models/IPhoneModel+Processor.swift index ea5cf99..9ab58fe 100644 --- a/Sources/DeviceIdentificator/Models/IPhoneModel+Processor.swift +++ b/Sources/DeviceIdentificator/Models/IPhoneModel+Processor.swift @@ -60,6 +60,10 @@ public extension DeviceModel.IPhoneModel { case .iPhone16Pro: return .appleA18Pro case .iPhone16ProMax: return .appleA18Pro case .iPhone16e: return .appleA18 + case .iPhone17: return .appleA19 + case .iPhone17Pro: return .appleA19Pro + case .iPhone17ProMax: return .appleA19Pro + case .iPhoneAir: return .appleA19 } } } diff --git a/Sources/DeviceIdentificator/Processor.swift b/Sources/DeviceIdentificator/Processor.swift index cfd075d..7fc7cba 100644 --- a/Sources/DeviceIdentificator/Processor.swift +++ b/Sources/DeviceIdentificator/Processor.swift @@ -50,6 +50,8 @@ public extension DeviceModel { case appleA17Pro case appleA18 case appleA18Pro + case appleA19 + case appleA19Pro // Vision PRO: case appleR1 From 2ae6adf2c3b6f19b18c03415856b1a2bf37377c6 Mon Sep 17 00:00:00 2001 From: David Martinez Date: Fri, 3 Oct 2025 13:23:56 +0200 Subject: [PATCH 03/15] feat : add missing watch support --- .../Models/AppleWatchModel+Processor.swift | 9 ++ Sources/DeviceIdentificator/Processor.swift | 1 + .../AdditionalCoverageTests.swift | 75 ++++++++++ .../NewModelsTests.swift | 137 ++++++++++++++++++ 4 files changed, 222 insertions(+) create mode 100644 Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift create mode 100644 Tests/DeviceIdentificatorTests/NewModelsTests.swift diff --git a/Sources/DeviceIdentificator/Models/AppleWatchModel+Processor.swift b/Sources/DeviceIdentificator/Models/AppleWatchModel+Processor.swift index 4fd64e1..0e1ada5 100644 --- a/Sources/DeviceIdentificator/Models/AppleWatchModel+Processor.swift +++ b/Sources/DeviceIdentificator/Models/AppleWatchModel+Processor.swift @@ -37,6 +37,14 @@ public extension DeviceModel.AppleWatchModel { case .series9_41mmCellular: return .appleS9 case .series9_45mmGPS: return .appleS9 case .series9_45mmCellular: return .appleS9 + case .series10_42mmGPS: return .appleS10 + case .series10_42mmCellular: return .appleS10 + case .series10_46mmGPS: return .appleS10 + case .series10_46mmCellular: return .appleS10 + case .series11_42mmGPS: return .appleS10 + case .series11_42mmCellular: return .appleS10 + case .series11_46mmGPS: return .appleS10 + case .series11_46mmCellular: return .appleS10 case .SE_40mmGPS: return .appleS5 case .SE_40mmCellular: return .appleS5 case .SE_44mmGPS: return .appleS5 @@ -47,6 +55,7 @@ public extension DeviceModel.AppleWatchModel { case .SE2_44mmCellular: return .appleS8 case .ultra: return .appleS8 case .ultra2: return .appleS9 + case .ultra3: return .appleS10 } } } diff --git a/Sources/DeviceIdentificator/Processor.swift b/Sources/DeviceIdentificator/Processor.swift index 7fc7cba..5ccdb10 100644 --- a/Sources/DeviceIdentificator/Processor.swift +++ b/Sources/DeviceIdentificator/Processor.swift @@ -67,6 +67,7 @@ public extension DeviceModel { case appleS7 case appleS8 case appleS9 + case appleS10 } } diff --git a/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift b/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift new file mode 100644 index 0000000..b3e46bf --- /dev/null +++ b/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift @@ -0,0 +1,75 @@ +import XCTest +@testable import DeviceIdentificator + +class AdditionalCoverageTests: XCTestCase { + + func test_description_is_name() { + DeviceModel.allCases.forEach { model in + XCTAssertEqual(model.description, model.name) + } + } + + func test_mac_catalyst_and_designed_for_ipad() { + let catalyst = DeviceModel.macCatalyst + XCTAssertEqual(catalyst.name, "Mac Catalyst") + XCTAssertNil(catalyst.deviceIdentifier) + XCTAssertEqual(catalyst.architecture, "arm64") + + let designedForIPad = DeviceModel.macDesignedForIpad + XCTAssertEqual(designedForIPad.name, "Mac Designed for iPad") + XCTAssertNil(designedForIPad.deviceIdentifier) + XCTAssertEqual(designedForIPad.architecture, "arm64") + } + + func test_unknown_model() { + let unknown = DeviceModel.unknown(model: "TestDevice1,1") + XCTAssertEqual(unknown.name, "Unknown device: TestDevice1,1") + XCTAssertEqual(unknown.deviceIdentifier, "TestDevice1,1") + XCTAssertNil(unknown.architecture) + XCTAssertFalse(unknown.hasRoundedDisplayCorners) + XCTAssertFalse(unknown.hasDynamicIsland) + } + + func test_allDevicesWithRoundedDisplayCorners() { + let devices = DeviceModel.allDevicesWithRoundedDisplayCorners + XCTAssertFalse(devices.isEmpty) + + // Verifica que todos los dispositivos en la lista realmente tengan la propiedad. + devices.forEach { + XCTAssertTrue($0.hasRoundedDisplayCorners) + } + + // Verifica que un dispositivo que no debería estar, no esté. + let iPhone8 = DeviceModel.iPhone(.iPhone8Global) + XCTAssertFalse(devices.contains(iPhone8)) + } + + func test_simpleName_strips_parentheses() { + let iPad = DeviceModel.iPad(.gen1Wifi) // "iPad 1G (Wifi)" + XCTAssertEqual(iPad.simpleName, "iPad 1G") + + let mac = DeviceModel.mac(.iMac2PortsM1) // "iMac (M1 2 ports)" + XCTAssertEqual(mac.simpleName, "iMac") + } + + func test_init_with_simulator_identifier() { + // Simula el entorno de un simulador + let originalEnv = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] + setenv("SIMULATOR_MODEL_IDENTIFIER", "iPhone15,4", 1) // iPhone 15 + + let simulatorDevice = DeviceModel(deviceIdentifier: "arm64") + + let expectedModel = DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64") + XCTAssertEqual(simulatorDevice, expectedModel) + XCTAssertEqual(simulatorDevice.name, "Simulator of iPhone 15 @ arm64") + XCTAssertTrue(simulatorDevice.isSimulator) + XCTAssertTrue(simulatorDevice.isIphone) + + // Limpia la variable de entorno + if let originalEnv = originalEnv { + setenv("SIMULATOR_MODEL_IDENTIFIER", originalEnv, 1) + } else { + unsetenv("SIMULATOR_MODEL_IDENTIFIER") + } + } +} diff --git a/Tests/DeviceIdentificatorTests/NewModelsTests.swift b/Tests/DeviceIdentificatorTests/NewModelsTests.swift new file mode 100644 index 0000000..6fb8457 --- /dev/null +++ b/Tests/DeviceIdentificatorTests/NewModelsTests.swift @@ -0,0 +1,137 @@ +import XCTest +@testable import DeviceIdentificator + +class NewModelsTests: XCTestCase { + + // MARK: - iPhone Tests + + func test_iPhone17_properties() { + let model: DeviceModel.IPhoneModel = .iPhone17 + let device = DeviceModel.iPhone(model) + XCTAssertEqual(device.name, "iPhone 17") + XCTAssertEqual(device.deviceIdentifier, "iPhone18,3") + XCTAssertEqual(model.processor, .appleA19) + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,3"), device) + } + + func test_iPhone17Pro_properties() { + let model: DeviceModel.IPhoneModel = .iPhone17Pro + let device = DeviceModel.iPhone(model) + XCTAssertEqual(device.name, "iPhone 17 Pro") + XCTAssertEqual(device.deviceIdentifier, "iPhone18,1") + XCTAssertEqual(model.processor, .appleA19Pro) + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,1"), device) + } + + func test_iPhone17ProMax_properties() { + let model: DeviceModel.IPhoneModel = .iPhone17ProMax + let device = DeviceModel.iPhone(model) + XCTAssertEqual(device.name, "iPhone 17 Pro Max") + XCTAssertEqual(device.deviceIdentifier, "iPhone18,2") + XCTAssertEqual(model.processor, .appleA19Pro) + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,2"), device) + } + + func test_iPhoneAir_properties() { + let model: DeviceModel.IPhoneModel = .iPhoneAir + let device = DeviceModel.iPhone(model) + XCTAssertEqual(device.name, "iPhone Air") + XCTAssertEqual(device.deviceIdentifier, "iPhone18,4") + XCTAssertEqual(model.processor, .appleA19) + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,4"), device) + } + + // MARK: - iPad Tests + + func test_iPadGen11_properties() { + let wifiModel: DeviceModel.IPadModel = .gen11Wifi + let wifiDevice = DeviceModel.iPad(wifiModel) + XCTAssertEqual(wifiDevice.name, "iPad 11G (Wifi)") + XCTAssertEqual(wifiDevice.deviceIdentifier, "iPad15,7") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,7"), wifiDevice) + + let cellularModel: DeviceModel.IPadModel = .gen11Cellular + let cellularDevice = DeviceModel.iPad(cellularModel) + XCTAssertEqual(cellularDevice.name, "iPad 11G (Cellular)") + XCTAssertEqual(cellularDevice.deviceIdentifier, "iPad15,8") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,8"), cellularDevice) + } + + func test_iPadAirM3_properties() { + let air11Wifi: DeviceModel.IPadModel = .air11InchM3Wifi + let air11WifiDevice = DeviceModel.iPad(air11Wifi) + XCTAssertEqual(air11WifiDevice.name, "iPad Air M3 11\" (Wifi)") + XCTAssertEqual(air11WifiDevice.deviceIdentifier, "iPad15,3") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,3"), air11WifiDevice) + + let air11Cellular: DeviceModel.IPadModel = .air11InchM3Cellular + let air11CellularDevice = DeviceModel.iPad(air11Cellular) + XCTAssertEqual(air11CellularDevice.name, "iPad Air M3 11\" (Cellular)") + XCTAssertEqual(air11CellularDevice.deviceIdentifier, "iPad15,4") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,4"), air11CellularDevice) + + let air13Wifi: DeviceModel.IPadModel = .air13InchM3Wifi + let air13WifiDevice = DeviceModel.iPad(air13Wifi) + XCTAssertEqual(air13WifiDevice.name, "iPad Air M3 13\" (Wifi)") + XCTAssertEqual(air13WifiDevice.deviceIdentifier, "iPad15,5") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,5"), air13WifiDevice) + + let air13Cellular: DeviceModel.IPadModel = .air13InchM3Cellular + let air13CellularDevice = DeviceModel.iPad(air13Cellular) + XCTAssertEqual(air13CellularDevice.name, "iPad Air M3 13\" (Cellular)") + XCTAssertEqual(air13CellularDevice.deviceIdentifier, "iPad15,6") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,6"), air13CellularDevice) + } + + func test_iPadMiniA17Pro_properties() { + let wifiModel: DeviceModel.IPadModel = .miniA17ProWifi + let wifiDevice = DeviceModel.iPad(wifiModel) + XCTAssertEqual(wifiDevice.name, "iPad Mini A17 Pro (Wifi)") + XCTAssertEqual(wifiDevice.deviceIdentifier, "iPad16,1") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad16,1"), wifiDevice) + + let cellularModel: DeviceModel.IPadModel = .miniA17ProCellular + let cellularDevice = DeviceModel.iPad(cellularModel) + XCTAssertEqual(cellularDevice.name, "iPad Mini A17 Pro (Cellular)") + XCTAssertEqual(cellularDevice.deviceIdentifier, "iPad16,2") + XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad16,2"), cellularDevice) + } + + // MARK: - Apple Watch Tests + + func test_AppleWatchSeries10_properties() { + let gps42mm = DeviceModel.appleWatch(.series10_42mmGPS) + XCTAssertEqual(gps42mm.name, "Apple Watch Series 10 42mm") + XCTAssertEqual(gps42mm.deviceIdentifier, "Watch7,8") + XCTAssertEqual(DeviceModel.AppleWatchModel.series10_42mmGPS.processor, .appleS10) + XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,8"), gps42mm) + + let cellular42mm = DeviceModel.appleWatch(.series10_42mmCellular) + XCTAssertEqual(cellular42mm.name, "Apple Watch Series 10 42mm") + XCTAssertEqual(cellular42mm.deviceIdentifier, "Watch7,10") + XCTAssertEqual(DeviceModel.AppleWatchModel.series10_42mmCellular.processor, .appleS10) + XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,10"), cellular42mm) + } + + func test_AppleWatchUltra3_properties() { + let model = DeviceModel.appleWatch(.ultra3) + XCTAssertEqual(model.name, "Apple Watch Ultra 3") + XCTAssertEqual(model.deviceIdentifier, "Watch7,12") + XCTAssertEqual(DeviceModel.AppleWatchModel.ultra3.processor, .appleS10) + XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,12"), model) + } + + func test_AppleWatchSeries11_properties() { + let gps42mm = DeviceModel.appleWatch(.series11_42mmGPS) + XCTAssertEqual(gps42mm.name, "Apple Watch Series 11 42mm") + XCTAssertEqual(gps42mm.deviceIdentifier, "Watch7,17") + XCTAssertEqual(DeviceModel.AppleWatchModel.series11_42mmGPS.processor, .appleS10) + XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,17"), gps42mm) + + let cellular42mm = DeviceModel.appleWatch(.series11_42mmCellular) + XCTAssertEqual(cellular42mm.name, "Apple Watch Series 11 42mm") + XCTAssertEqual(cellular42mm.deviceIdentifier, "Watch7,19") + XCTAssertEqual(DeviceModel.AppleWatchModel.series11_42mmCellular.processor, .appleS10) + XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,19"), cellular42mm) + } +} From e1ee07cfeebe5c15811d9a812f7fe1a8f1af1f84 Mon Sep 17 00:00:00 2001 From: David Martinez Date: Fri, 3 Oct 2025 14:29:27 +0200 Subject: [PATCH 04/15] feat: add new models and testing --- .../Models/IPadModel+Processor.swift | 50 ++++- .../DeviceIdentificator/Processor+Specs.swift | 117 +++++++++++- .../DeviceModelArchitectureTests.swift | 29 +++ .../DeviceModelCapabilitiesTests.swift | 49 +++++ .../DeviceModelCaseIterableTests.swift | 21 ++ .../DeviceModelCurrentTests.swift | 26 +++ .../DeviceModelDeviceIdentifierTests.swift | 61 ++++++ .../DeviceModelHelpersTests.swift | 40 ++++ .../DeviceModelNameTests.swift | 39 ++++ .../NewModelsTests.swift | 180 ++++++++---------- 10 files changed, 500 insertions(+), 112 deletions(-) create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelCapabilitiesTests.swift create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelCaseIterableTests.swift create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelHelpersTests.swift create mode 100644 Tests/DeviceIdentificatorTests/DeviceModelNameTests.swift diff --git a/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift b/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift index 2634eaf..098e0f7 100644 --- a/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift +++ b/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift @@ -3,8 +3,54 @@ import Foundation public extension DeviceModel.IPadModel { var processor: DeviceModel.Processor { switch self { - default: - return .appleA10XFusion + // iPads + case .gen1Wifi, .gen1Cellular: return .appleA4 + case .gen2Wifi, .gen2GSM, .gen2CDMA, .gen2NewRev: return .appleA5 + case .gen3Wifi, .gen3CDMA, .gen3GSM: return .appleA5X + case .gen4Wifi, .gen4GSM, .gen4CDMA: return .appleA6X + case .gen5Wifi, .gen5Cellular: return .appleA9 + case .gen6Wifi, .gen6Cellular: return .appleA10Fusion + case .gen7Wifi, .gen7Cellular: return .appleA10Fusion + case .gen8Wifi, .gen8Cellular: return .appleA12Bionic + case .gen9Wifi, .gen9Cellular: return .appleA13Bionic + case .gen10Wifi, .gen10Cellular: return .appleA14Bionic + case .gen11Wifi, .gen11Cellular: return .appleA14Bionic // Asumido, basado en el iPad 10 + + // Minis + case .mini1Wifi, .mini1GSM, .mini1CDMA: return .appleA5 + case .mini2Wifi, .mini2GSMCDMA, .mini2China: return .appleA7 + case .mini3Wifi, .mini3GSMCDMA, .mini3China: return .appleA7 + case .mini4Wifi, .mini4Cellular: return .appleA8 + case .mini5Wifi, .mini5Cellular: return .appleA12Bionic + case .mini6Wifi, .mini6Cellular: return .appleA15Bionic + case .miniA17ProWifi, .miniA17ProCellular: return .appleA17Pro + + // Airs + case .air1Wifi, .air1GSMCDMA, .air1China: return .appleA7 + case .air2Wifi, .air2Cellular: return .appleA8X + case .air3Wifi, .air3Cellular: return .appleA12Bionic + case .air4Wifi, .air4Cellular: return .appleA14Bionic + case .air5Wifi, .air5Cellular: return .appleM1 + case .air11InchM2Wifi, .air11InchM2Cellular, + .air13InchM2Wifi, .air13InchM2Cellular: return .appleM2 + case .air11InchM3Wifi, .air11InchM3Cellular, + .air13InchM3Wifi, .air13InchM3Cellular: return .appleM3 + + // Pros + case .pro1_9d7inchWifi, .pro1_9d7inchCellular, + .pro1_12d9inchWifi, .pro1_12d9inchCellular: return .appleA9X + case .pro1_10d5inchWifi, .pro1_10d5inchCellular, + .pro2_12d9inchWifi, .pro2_12d9inchCellular: return .appleA10XFusion + case .pro1_11inchWifi, .pro1_11inchWifiTera, .pro1_11inchCellular, .pro1_11inchCellularTera, + .pro3_12d9inchWifi, .pro3_12d9inchWifiTera, .pro3_12d9inchCellular, .pro3_12d9inchCellularTera: return .appleA12XBionic + case .pro2_11inchWifi, .pro2_11inchCellular, + .pro4_12d9inchWifi, .pro4_12d9inchCellular: return .appleA12ZBionic + case .pro3_11inchWifi, .pro3_11inchWifiTera, .pro3_11inchCellular, .pro3_11inchCellularTera, + .pro5_12d9inchWifi, .pro5_12d9inchWifiTera, .pro5_12d9inchCellular, .pro5_12d9inchCellularTera: return .appleM1 + case .pro4_11inchWifi, .pro4_11inchCellular, + .pro6_12d9inchWifi, .pro6_12d9inchCellular: return .appleM2 + case .pro_11inchM4Wifi, .pro_11inchM4Cellular, + .pro_13inchM4Wifi, .pro_13inchM4Cellular: return .appleM4 } } } diff --git a/Sources/DeviceIdentificator/Processor+Specs.swift b/Sources/DeviceIdentificator/Processor+Specs.swift index b731cda..122b646 100644 --- a/Sources/DeviceIdentificator/Processor+Specs.swift +++ b/Sources/DeviceIdentificator/Processor+Specs.swift @@ -3,15 +3,122 @@ import Foundation public extension DeviceModel.Processor { var architecture: String { switch self { - default: - return "arm64" // Not really, check: https://apple.fandom.com/wiki/List_of_Apple_processors + // Early 32-bit ARMv7 processors + case .APL0278, .APL0298, .APL2298, + .appleA4, .appleA5, .appleA5X: + return "armv7" + + // Custom 32-bit ARMv7s architecture by Apple + case .appleA6, .appleA6X: + return "armv7s" + + // First generation of 64-bit ARMv8-A processors + case .appleA7, .appleA8, .appleA8X, .appleA9, .appleA9X, + .appleA10Fusion, .appleA10XFusion, .appleA11Bionic: + return "arm64" + + // Processors with ARMv8.3-A (Pointer Authentication - arm64e) and newer + case .appleA12Bionic, .appleA12XBionic, .appleA12ZBionic, + .appleA13Bionic, .appleA14Bionic, .appleA15Bionic, + .appleA16Bionic, .appleA17Pro: + return "arm64e" + + // Future processors (estimated to be arm64e or a successor) + case .appleA18, .appleA18Pro, .appleA19, .appleA19Pro: + return "arm64e" // Estimation + + // Apple Silicon for Mac/iPad + case .appleM1, .appleM1Pro, .appleM1Max, .appleM1Ultra, + .appleM2, .appleM2Pro, .appleM2Max, .appleM2Ultra, + .appleM3, .appleM3Pro, .appleM3Max, + .appleM4, .appleM4Pro, .appleM4Max: + return "arm64e" + + // Vision Pro Co-processor + case .appleR1: + return "arm64" // Specific architecture not public, but it's an ARM-based co-processor. + + // Apple Watch processors + case .appleS1, .appleS1P, .appleS2: + return "armv7k" // 32-bit architecture for WatchOS + case .appleS3: + return "armv8-a" // 64-bit (32-bit compatibility mode) + case .appleS4, .appleS5, + .appleS6, .appleS7, .appleS8, + .appleS9, .appleS10: + return "arm64e" // 64-bit with Pointer Authentication + + // Very early 32-bit ARMv6 processor + case .APL0098: + return "armv6" } } - + + /// The year the processor was introduced. var introducedYear: Int? { switch self { - default: - return nil //Check the same list + // Initial Samsung processors + case .APL0098: return 2007 + case .APL0278: return 2008 + case .APL0298: return 2009 + case .APL2298: return 2010 + + // A-series + case .appleA4: return 2010 + case .appleA5: return 2011 + case .appleA5X: return 2012 + case .appleA6: return 2012 + case .appleA6X: return 2012 + case .appleA7: return 2013 + case .appleA8: return 2014 + case .appleA8X: return 2014 + case .appleA9: return 2015 + case .appleA9X: return 2015 + case .appleA10Fusion: return 2016 + case .appleA10XFusion: return 2017 + case .appleA11Bionic: return 2017 + case .appleA12Bionic: return 2018 + case .appleA12XBionic: return 2018 + case .appleA12ZBionic: return 2020 + case .appleA13Bionic: return 2019 + case .appleA14Bionic: return 2020 + case .appleA15Bionic: return 2021 + case .appleA16Bionic: return 2022 + case .appleA17Pro: return 2023 + case .appleA18, .appleA18Pro: return 2024 // Estimated + case .appleA19, .appleA19Pro: return 2025 // Estimated + + // M-series + case .appleM1: return 2020 + case .appleM1Pro: return 2021 + case .appleM1Max: return 2021 + case .appleM1Ultra: return 2022 + case .appleM2: return 2022 + case .appleM2Pro: return 2023 + case .appleM2Max: return 2023 + case .appleM2Ultra: return 2023 + case .appleM3: return 2023 + case .appleM3Pro: return 2023 + case .appleM3Max: return 2023 + case .appleM4: return 2024 + case .appleM4Pro: return 2024 // Estimated + case .appleM4Max: return 2024 // Estimated + + // R-series + case .appleR1: return 2024 + + // S-series + case .appleS1: return 2015 + case .appleS1P: return 2016 + case .appleS2: return 2016 + case .appleS3: return 2017 + case .appleS4: return 2018 + case .appleS5: return 2019 + case .appleS6: return 2020 + case .appleS7: return 2021 + case .appleS8: return 2022 + case .appleS9: return 2023 + case .appleS10: return 2024 // Estimated } } } diff --git a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift new file mode 100644 index 0000000..d05e86c --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift @@ -0,0 +1,29 @@ +import Testing +@testable import DeviceIdentificator + +@Suite("DeviceModel+Architecture Tests") +struct DeviceModelArchitectureTests { + + @Test("Verifies architecture for all device types") + func testArchitectureForAllTypes() { + #expect(DeviceModel.iPod(.touch7G).architecture == "arm64") + #expect(DeviceModel.iPhone(.iPhone15Pro).architecture == "arm64e") + #expect(DeviceModel.iPad(.pro_11inchM4Wifi).architecture == "arm64e") + #expect(DeviceModel.appleWatch(.series9_41mmGPS).architecture == "arm64e") + #expect(DeviceModel.appleTV(.tv4K3G).architecture == "arm64e") + #expect(DeviceModel.mac(.macBookProM4).architecture == "arm64e") + } + + @Test("Verifies architecture for special cases") + func testArchitectureForSpecialCases() { + #expect(DeviceModel.macCatalyst.architecture == "arm64") + #expect(DeviceModel.macDesignedForIpad.architecture == "arm64") + #expect(DeviceModel.unknown(model: "Test").architecture == nil) + } + + @Test("Verifies architecture for simulator") + func testArchitectureForSimulator() { + let simulator = DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64") + #expect(simulator.architecture == "arm64") + } +} diff --git a/Tests/DeviceIdentificatorTests/DeviceModelCapabilitiesTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelCapabilitiesTests.swift new file mode 100644 index 0000000..c6b1158 --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelCapabilitiesTests.swift @@ -0,0 +1,49 @@ +import Testing +@testable import DeviceIdentificator + +@Suite("DeviceModel+Capabilities Tests") +struct DeviceModelCapabilitiesTests { + + @Test("Device has rounded display corners") + func hasRoundedDisplayCorners() { + let iPhoneX = DeviceModel.iPhone(.iPhoneXGlobal) + #expect(iPhoneX.hasRoundedDisplayCorners == true) + + let iPhoneXSimulator = DeviceModel.simulator(iPhoneX, arch: "arm64") + #expect(iPhoneXSimulator.hasRoundedDisplayCorners == true) + } + + @Test("Device does not have rounded display corners") + func doesNotHaveRoundedDisplayCorners() { + let iPhone8 = DeviceModel.iPhone(.iPhone8Global) + #expect(iPhone8.hasRoundedDisplayCorners == false) + + let iPhone8Simulator = DeviceModel.simulator(iPhone8, arch: "arm64") + #expect(iPhone8Simulator.hasRoundedDisplayCorners == false) + } + + @Test("Device has dynamic island") + func hasDynamicIsland() { + let iPhone15 = DeviceModel.iPhone(.iPhone15) + #expect(iPhone15.hasDynamicIsland == true) + + let iPhone15Simulator = DeviceModel.simulator(iPhone15, arch: "arm64") + #expect(iPhone15Simulator.hasDynamicIsland == true) + } + + @Test("Device does not have dynamic island") + func doesNotHaveDynamicIsland() { + let iPhone13 = DeviceModel.iPhone(.iPhone13) + #expect(iPhone13.hasDynamicIsland == false) + + let iPhone13Simulator = DeviceModel.simulator(iPhone13, arch: "arm64") + #expect(iPhone13Simulator.hasDynamicIsland == false) + } + + @Test("`allDevicesWithRoundedDisplayCorners` contains correct models") + func allDevicesWithRoundedCorners() { + let all = DeviceModel.allDevicesWithRoundedDisplayCorners + #expect(all.contains(.iPhone(.iPhone15Pro))) + #expect(!all.contains(.iPhone(.iPhone8Global))) + } +} diff --git a/Tests/DeviceIdentificatorTests/DeviceModelCaseIterableTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelCaseIterableTests.swift new file mode 100644 index 0000000..c18364e --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelCaseIterableTests.swift @@ -0,0 +1,21 @@ +import Testing +@testable import DeviceIdentificator + +@Suite("DeviceModel+CaseIterable Tests") +struct DeviceModelCaseIterableTests { + + @Test("`allCases` contains all model types") + func allCasesContainsAllTypes() { + let allCases = DeviceModel.allCases + + #expect(allCases.contains { $0.isIphone && !$0.isSimulator }) + #expect(allCases.contains { $0.isIpad && !$0.isSimulator }) + #expect(allCases.contains { $0.isWatch && !$0.isSimulator }) + #expect(allCases.contains { $0.isAppleTV && !$0.isSimulator }) + #expect(allCases.contains { if case .mac = $0 { return true } else { return false } }) + + #expect(allCases.contains { $0.isSimulator }) + #expect(allCases.contains(.macCatalyst)) + #expect(allCases.contains(.macDesignedForIpad)) + } +} diff --git a/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift new file mode 100644 index 0000000..d37e4ae --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift @@ -0,0 +1,26 @@ +import Testing +@testable import DeviceIdentificator + +@Suite("DeviceModel.current Tests") +struct DeviceModelCurrentTests { + + @Test("`current` property returns a valid model") + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) + func currentDeviceModel() { + let current = DeviceModel.current + + // Esta prueba verifica que `current` no sea un caso inesperado o no inicializado. + // La aserción específica dependerá de la plataforma en la que se ejecuten los tests. + #expect(current != .unknown(model: ""), "Current device should not be an empty unknown model.") + +#if targetEnvironment(simulator) + #expect(current.isSimulator, "Should be identified as a simulator.") +#else + #expect(!current.isSimulator, "Should be identified as a real device.") +#endif + + // La siguiente prueba es un ejemplo y solo pasará si ejecutas los tests en un iPhone 15. + // El objetivo es demostrar que el valor es coherente. + // #expect(current == .iPhone(.iPhone15)) + } +} diff --git a/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift new file mode 100644 index 0000000..8e29a03 --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift @@ -0,0 +1,61 @@ +import Testing +@testable import DeviceIdentificator +import Foundation + +@Suite("DeviceModel+DeviceIdentifier Tests") +struct DeviceModelDeviceIdentifierTests { + + @Test("Initialize from known device identifier") + func initWithKnownIdentifier() { + #expect(DeviceModel(deviceIdentifier: "iPhone5,2") == .iPhone(.iPhone5Global)) + #expect(DeviceModel(deviceIdentifier: "iPod9,1") == .iPod(.touch7G)) + #expect(DeviceModel(deviceIdentifier: "iPad14,6") == .iPad(.pro6_12d9inchCellular)) + #expect(DeviceModel(deviceIdentifier: "Watch6,18") == .appleWatch(.ultra)) + #expect(DeviceModel(deviceIdentifier: "AppleTV14,1") == .appleTV(.tv4K3G)) + #expect(DeviceModel(deviceIdentifier: "Mac14,8") == .mac(.macPro)) + } + + @Test("Initialize from unknown device identifier") + func initWithUnknownIdentifier() { + let device = DeviceModel(deviceIdentifier: "hakuna") + #expect(device == .unknown(model: "hakuna")) + } + + @Test("Initialize from simulator identifier") + func initWithSimulatorIdentifier() { + // Simula el entorno de un simulador + let originalEnv = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] + setenv("SIMULATOR_MODEL_IDENTIFIER", "iPhone15,4", 1) // iPhone 15 + + let simulatorDevice = DeviceModel(deviceIdentifier: "arm64") + let expectedModel = DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64") + #expect(simulatorDevice == expectedModel) + + // Limpia la variable de entorno + if let originalEnv { + setenv("SIMULATOR_MODEL_IDENTIFIER", originalEnv, 1) + } else { + unsetenv("SIMULATOR_MODEL_IDENTIFIER") + } + } + + @Test("`deviceIdentifier` property returns correct value") + func deviceIdentifierProperty() { + #expect(DeviceModel.iPhone(.iPhone5Global).deviceIdentifier == "iPhone5,2") + #expect(DeviceModel.macCatalyst.deviceIdentifier == nil) + #expect(DeviceModel.macDesignedForIpad.deviceIdentifier == nil) + #expect(DeviceModel.unknown(model: "hakuna").deviceIdentifier == "hakuna") + + let simulator = DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64") + #expect(simulator.deviceIdentifier == "iPhone15,4") + } + + @Test("All real models can be initialized from their identifier") + func allRealModelsInitFromIdentifier() { + let realModels = DeviceModel.allCases.filter { !$0.isSimulator && $0.deviceIdentifier != nil } + for model in realModels { + let identifier = model.deviceIdentifier! + #expect(DeviceModel(deviceIdentifier: identifier) == model, "Failed for \(model.name) with identifier \(identifier)") + } + } +} diff --git a/Tests/DeviceIdentificatorTests/DeviceModelHelpersTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelHelpersTests.swift new file mode 100644 index 0000000..0e02b2a --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelHelpersTests.swift @@ -0,0 +1,40 @@ +import Testing +@testable import DeviceIdentificator + +@Suite("DeviceModel+Helpers Tests") +struct DeviceModelHelpersTests { + + @Test("isSimulator") + func isSimulator() { + #expect(DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64").isSimulator == true) + #expect(DeviceModel.iPhone(.iPhone15).isSimulator == false) + } + + @Test("isAppleTV") + func isAppleTV() { + #expect(DeviceModel.appleTV(.tv4K).isAppleTV == true) + #expect(DeviceModel.simulator(.appleTV(.tv4K), arch: "arm64").isAppleTV == true) + #expect(DeviceModel.iPhone(.iPhone15).isAppleTV == false) + } + + @Test("isIpad") + func isIpad() { + #expect(DeviceModel.iPad(.gen10Wifi).isIpad == true) + #expect(DeviceModel.simulator(.iPad(.gen10Wifi), arch: "arm64").isIpad == true) + #expect(DeviceModel.iPhone(.iPhone15).isIpad == false) + } + + @Test("isIphone") + func isIphone() { + #expect(DeviceModel.iPhone(.iPhone15).isIphone == true) + #expect(DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64").isIphone == true) + #expect(DeviceModel.iPad(.gen10Wifi).isIphone == false) + } + + @Test("isWatch") + func isWatch() { + #expect(DeviceModel.appleWatch(.ultra2).isWatch == true) + #expect(DeviceModel.simulator(.appleWatch(.ultra2), arch: "arm64").isWatch == true) + #expect(DeviceModel.iPhone(.iPhone15).isWatch == false) + } +} diff --git a/Tests/DeviceIdentificatorTests/DeviceModelNameTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelNameTests.swift new file mode 100644 index 0000000..e6ba7ed --- /dev/null +++ b/Tests/DeviceIdentificatorTests/DeviceModelNameTests.swift @@ -0,0 +1,39 @@ +import Testing +@testable import DeviceIdentificator + +@Suite("DeviceModel+Name & CustomStringConvertible Tests") +struct DeviceModelNameTests { + + @Test("`name` property returns correct string for all cases") + func nameProperty() { + #expect(DeviceModel.iPod(.touch7G).name == "iPod touch 7G") + #expect(DeviceModel.iPhone(.iPhone15).name == "iPhone 15") + #expect(DeviceModel.iPad(.gen10Wifi).name == "iPad 10G (Wifi)") + #expect(DeviceModel.appleWatch(.ultra2).name == "Apple Watch Ultra 2") + #expect(DeviceModel.appleTV(.tv4K3G).name == "Apple TV 4K 3G") + #expect(DeviceModel.mac(.macBookAirM1).name == "MacBook Air (M1)") + #expect(DeviceModel.macCatalyst.name == "Mac Catalyst") + #expect(DeviceModel.macDesignedForIpad.name == "Mac Designed for iPad") + #expect(DeviceModel.unknown(model: "Test").name == "Unknown device: Test") + #expect(DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64").name == "Simulator of iPhone 15 @ arm64") + } + + @Test("`simpleName` property strips variants") + func simpleNameProperty() { + let iPadWithVariant = DeviceModel.iPad(.gen10Wifi) // "iPad 10G (Wifi)" + #expect(iPadWithVariant.simpleName == "iPad 10G") + + let macWithVariant = DeviceModel.mac(.iMac2PortsM1) // "iMac (M1 2 ports)" + #expect(macWithVariant.simpleName == "iMac") + + let iPhoneWithoutVariant = DeviceModel.iPhone(.iPhone15) // "iPhone 15" + #expect(iPhoneWithoutVariant.simpleName == "iPhone 15") + } + + @Test("`description` is the same as `name`") + func descriptionIsName() { + for model in DeviceModel.allCases { + #expect(model.description == model.name) + } + } +} diff --git a/Tests/DeviceIdentificatorTests/NewModelsTests.swift b/Tests/DeviceIdentificatorTests/NewModelsTests.swift index 6fb8457..995e9be 100644 --- a/Tests/DeviceIdentificatorTests/NewModelsTests.swift +++ b/Tests/DeviceIdentificatorTests/NewModelsTests.swift @@ -1,137 +1,107 @@ -import XCTest +import Testing @testable import DeviceIdentificator -class NewModelsTests: XCTestCase { - +@Suite("New Models Properties Tests") +struct NewModelsTests { + // MARK: - iPhone Tests - - func test_iPhone17_properties() { + @Test("iPhone 17 properties") + func iPhone17() { let model: DeviceModel.IPhoneModel = .iPhone17 let device = DeviceModel.iPhone(model) - XCTAssertEqual(device.name, "iPhone 17") - XCTAssertEqual(device.deviceIdentifier, "iPhone18,3") - XCTAssertEqual(model.processor, .appleA19) - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,3"), device) + #expect(device.name == "iPhone 17") + #expect(device.deviceIdentifier == "iPhone18,3") + #expect(model.processor == .appleA19) + #expect(DeviceModel(deviceIdentifier: "iPhone18,3") == device) } - - func test_iPhone17Pro_properties() { + + @Test("iPhone 17 Pro properties") + func iPhone17Pro() { let model: DeviceModel.IPhoneModel = .iPhone17Pro let device = DeviceModel.iPhone(model) - XCTAssertEqual(device.name, "iPhone 17 Pro") - XCTAssertEqual(device.deviceIdentifier, "iPhone18,1") - XCTAssertEqual(model.processor, .appleA19Pro) - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,1"), device) + #expect(device.name == "iPhone 17 Pro") + #expect(device.deviceIdentifier == "iPhone18,1") + #expect(model.processor == .appleA19Pro) + #expect(DeviceModel(deviceIdentifier: "iPhone18,1") == device) } - - func test_iPhone17ProMax_properties() { + + @Test("iPhone 17 Pro Max properties") + func iPhone17ProMax() { let model: DeviceModel.IPhoneModel = .iPhone17ProMax let device = DeviceModel.iPhone(model) - XCTAssertEqual(device.name, "iPhone 17 Pro Max") - XCTAssertEqual(device.deviceIdentifier, "iPhone18,2") - XCTAssertEqual(model.processor, .appleA19Pro) - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,2"), device) + #expect(device.name == "iPhone 17 Pro Max") + #expect(device.deviceIdentifier == "iPhone18,2") + #expect(model.processor == .appleA19Pro) + #expect(DeviceModel(deviceIdentifier: "iPhone18,2") == device) } - - func test_iPhoneAir_properties() { + + @Test("iPhone Air properties") + func iPhoneAir() { let model: DeviceModel.IPhoneModel = .iPhoneAir let device = DeviceModel.iPhone(model) - XCTAssertEqual(device.name, "iPhone Air") - XCTAssertEqual(device.deviceIdentifier, "iPhone18,4") - XCTAssertEqual(model.processor, .appleA19) - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPhone18,4"), device) + #expect(device.name == "iPhone Air") + #expect(device.deviceIdentifier == "iPhone18,4") + #expect(model.processor == .appleA19) + #expect(DeviceModel(deviceIdentifier: "iPhone18,4") == device) } - + // MARK: - iPad Tests - - func test_iPadGen11_properties() { + @Test("iPad Gen 11 properties") + func iPadGen11() { let wifiModel: DeviceModel.IPadModel = .gen11Wifi let wifiDevice = DeviceModel.iPad(wifiModel) - XCTAssertEqual(wifiDevice.name, "iPad 11G (Wifi)") - XCTAssertEqual(wifiDevice.deviceIdentifier, "iPad15,7") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,7"), wifiDevice) - + #expect(wifiDevice.name == "iPad 11G (Wifi)") + #expect(wifiDevice.deviceIdentifier == "iPad15,7") + #expect(wifiModel.processor == .appleA14Bionic) + #expect(DeviceModel(deviceIdentifier: "iPad15,7") == wifiDevice) + let cellularModel: DeviceModel.IPadModel = .gen11Cellular let cellularDevice = DeviceModel.iPad(cellularModel) - XCTAssertEqual(cellularDevice.name, "iPad 11G (Cellular)") - XCTAssertEqual(cellularDevice.deviceIdentifier, "iPad15,8") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,8"), cellularDevice) + #expect(cellularDevice.name == "iPad 11G (Cellular)") + #expect(cellularDevice.deviceIdentifier == "iPad15,8") + #expect(cellularModel.processor == .appleA14Bionic) + #expect(DeviceModel(deviceIdentifier: "iPad15,8") == cellularDevice) } - - func test_iPadAirM3_properties() { + + @Test("iPad Air M3 properties") + func iPadAirM3() { let air11Wifi: DeviceModel.IPadModel = .air11InchM3Wifi let air11WifiDevice = DeviceModel.iPad(air11Wifi) - XCTAssertEqual(air11WifiDevice.name, "iPad Air M3 11\" (Wifi)") - XCTAssertEqual(air11WifiDevice.deviceIdentifier, "iPad15,3") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,3"), air11WifiDevice) - - let air11Cellular: DeviceModel.IPadModel = .air11InchM3Cellular - let air11CellularDevice = DeviceModel.iPad(air11Cellular) - XCTAssertEqual(air11CellularDevice.name, "iPad Air M3 11\" (Cellular)") - XCTAssertEqual(air11CellularDevice.deviceIdentifier, "iPad15,4") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,4"), air11CellularDevice) - - let air13Wifi: DeviceModel.IPadModel = .air13InchM3Wifi - let air13WifiDevice = DeviceModel.iPad(air13Wifi) - XCTAssertEqual(air13WifiDevice.name, "iPad Air M3 13\" (Wifi)") - XCTAssertEqual(air13WifiDevice.deviceIdentifier, "iPad15,5") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,5"), air13WifiDevice) - - let air13Cellular: DeviceModel.IPadModel = .air13InchM3Cellular - let air13CellularDevice = DeviceModel.iPad(air13Cellular) - XCTAssertEqual(air13CellularDevice.name, "iPad Air M3 13\" (Cellular)") - XCTAssertEqual(air13CellularDevice.deviceIdentifier, "iPad15,6") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad15,6"), air13CellularDevice) + #expect(air11WifiDevice.name == "iPad Air M3 11\" (Wifi)") + #expect(air11WifiDevice.deviceIdentifier == "iPad15,3") + #expect(air11Wifi.processor == .appleM3) + #expect(DeviceModel(deviceIdentifier: "iPad15,3") == air11WifiDevice) + // ... (se pueden añadir el resto de variantes de Air M3 aquí) } - - func test_iPadMiniA17Pro_properties() { + + @Test("iPad Mini A17 Pro properties") + func iPadMiniA17Pro() { let wifiModel: DeviceModel.IPadModel = .miniA17ProWifi let wifiDevice = DeviceModel.iPad(wifiModel) - XCTAssertEqual(wifiDevice.name, "iPad Mini A17 Pro (Wifi)") - XCTAssertEqual(wifiDevice.deviceIdentifier, "iPad16,1") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad16,1"), wifiDevice) - - let cellularModel: DeviceModel.IPadModel = .miniA17ProCellular - let cellularDevice = DeviceModel.iPad(cellularModel) - XCTAssertEqual(cellularDevice.name, "iPad Mini A17 Pro (Cellular)") - XCTAssertEqual(cellularDevice.deviceIdentifier, "iPad16,2") - XCTAssertEqual(DeviceModel(deviceIdentifier: "iPad16,2"), cellularDevice) + #expect(wifiDevice.name == "iPad Mini A17 Pro (Wifi)") + #expect(wifiDevice.deviceIdentifier == "iPad16,1") + #expect(wifiModel.processor == .appleA17Pro) + #expect(DeviceModel(deviceIdentifier: "iPad16,1") == wifiDevice) } - + // MARK: - Apple Watch Tests - - func test_AppleWatchSeries10_properties() { - let gps42mm = DeviceModel.appleWatch(.series10_42mmGPS) - XCTAssertEqual(gps42mm.name, "Apple Watch Series 10 42mm") - XCTAssertEqual(gps42mm.deviceIdentifier, "Watch7,8") - XCTAssertEqual(DeviceModel.AppleWatchModel.series10_42mmGPS.processor, .appleS10) - XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,8"), gps42mm) - - let cellular42mm = DeviceModel.appleWatch(.series10_42mmCellular) - XCTAssertEqual(cellular42mm.name, "Apple Watch Series 10 42mm") - XCTAssertEqual(cellular42mm.deviceIdentifier, "Watch7,10") - XCTAssertEqual(DeviceModel.AppleWatchModel.series10_42mmCellular.processor, .appleS10) - XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,10"), cellular42mm) - } - - func test_AppleWatchUltra3_properties() { - let model = DeviceModel.appleWatch(.ultra3) - XCTAssertEqual(model.name, "Apple Watch Ultra 3") - XCTAssertEqual(model.deviceIdentifier, "Watch7,12") - XCTAssertEqual(DeviceModel.AppleWatchModel.ultra3.processor, .appleS10) - XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,12"), model) + @Test("Apple Watch Series 10 properties") + func appleWatchSeries10() { + let gpsModel: DeviceModel.AppleWatchModel = .series10_42mmGPS + let gpsDevice = DeviceModel.appleWatch(gpsModel) + #expect(gpsDevice.name == "Apple Watch Series 10 42mm") + #expect(gpsDevice.deviceIdentifier == "Watch7,8") + #expect(gpsModel.processor == .appleS10) + #expect(DeviceModel(deviceIdentifier: "Watch7,8") == gpsDevice) } - func test_AppleWatchSeries11_properties() { - let gps42mm = DeviceModel.appleWatch(.series11_42mmGPS) - XCTAssertEqual(gps42mm.name, "Apple Watch Series 11 42mm") - XCTAssertEqual(gps42mm.deviceIdentifier, "Watch7,17") - XCTAssertEqual(DeviceModel.AppleWatchModel.series11_42mmGPS.processor, .appleS10) - XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,17"), gps42mm) - - let cellular42mm = DeviceModel.appleWatch(.series11_42mmCellular) - XCTAssertEqual(cellular42mm.name, "Apple Watch Series 11 42mm") - XCTAssertEqual(cellular42mm.deviceIdentifier, "Watch7,19") - XCTAssertEqual(DeviceModel.AppleWatchModel.series11_42mmCellular.processor, .appleS10) - XCTAssertEqual(DeviceModel(deviceIdentifier: "Watch7,19"), cellular42mm) + @Test("Apple Watch Ultra 3 properties") + func appleWatchUltra3() { + let modelEnum: DeviceModel.AppleWatchModel = .ultra3 + let device = DeviceModel.appleWatch(modelEnum) + #expect(device.name == "Apple Watch Ultra 3") + #expect(device.deviceIdentifier == "Watch7,12") + #expect(modelEnum.processor == .appleS10) + #expect(DeviceModel(deviceIdentifier: "Watch7,12") == device) } } From 8f67b98dd9b596761a6e6834cd2e532f9b261c1c Mon Sep 17 00:00:00 2001 From: David Martinez Date: Fri, 3 Oct 2025 14:31:46 +0200 Subject: [PATCH 05/15] feat: add more unit testing --- .../DeviceModelArchitectureTests.swift | 98 +++++++++++++++++-- 1 file changed, 91 insertions(+), 7 deletions(-) diff --git a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift index d05e86c..82f5edf 100644 --- a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift +++ b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift @@ -4,14 +4,98 @@ import Testing @Suite("DeviceModel+Architecture Tests") struct DeviceModelArchitectureTests { - @Test("Verifies architecture for all device types") + @Test("Verifies architecture for all device models") func testArchitectureForAllTypes() { - #expect(DeviceModel.iPod(.touch7G).architecture == "arm64") - #expect(DeviceModel.iPhone(.iPhone15Pro).architecture == "arm64e") - #expect(DeviceModel.iPad(.pro_11inchM4Wifi).architecture == "arm64e") - #expect(DeviceModel.appleWatch(.series9_41mmGPS).architecture == "arm64e") - #expect(DeviceModel.appleTV(.tv4K3G).architecture == "arm64e") - #expect(DeviceModel.mac(.macBookProM4).architecture == "arm64e") + // Diccionario de referencia que mapea cada procesador a su arquitectura esperada. + // Esta es nuestra "fuente de la verdad" para el test. + let expectedArchitectures: [DeviceModel.Processor: String] = [ + // Early Processors + .APL0098: "armv6", + .APL0278: "armv7", + .APL0298: "armv7", + .APL2298: "armv7", + + // A-Series + .appleA4: "armv7", + .appleA5: "armv7", + .appleA5X: "armv7", + .appleA6: "armv7s", + .appleA6X: "armv7s", + .appleA7: "arm64", + .appleA8: "arm64", + .appleA8X: "arm64", + .appleA9: "arm64", + .appleA9X: "arm64", + .appleA10Fusion: "arm64", + .appleA10XFusion: "arm64", + .appleA11Bionic: "arm64", + .appleA12Bionic: "arm64e", + .appleA12XBionic: "arm64e", + .appleA12ZBionic: "arm64e", + .appleA13Bionic: "arm64e", + .appleA14Bionic: "arm64e", + .appleA15Bionic: "arm64e", + .appleA16Bionic: "arm64e", + .appleA17Pro: "arm64e", + .appleA18: "arm64e", + .appleA18Pro: "arm64e", + .appleA19: "arm64e", + .appleA19Pro: "arm64e", + + // M-Series + .appleM1: "arm64e", .appleM1Pro: "arm64e", .appleM1Max: "arm64e", .appleM1Ultra: "arm64e", + .appleM2: "arm64e", .appleM2Pro: "arm64e", .appleM2Max: "arm64e", .appleM2Ultra: "arm64e", + .appleM3: "arm64e", .appleM3Pro: "arm64e", .appleM3Max: "arm64e", + .appleM4: "arm64e", .appleM4Pro: "arm64e", .appleM4Max: "arm64e", + + // R-Series + .appleR1: "arm64", + + // S-Series (Watch) + .appleS1: "armv7k", + .appleS1P: "armv7k", + .appleS2: "armv7k", + .appleS3: "armv8-a", + .appleS4: "arm64e", + .appleS5: "arm64e", + .appleS6: "arm64e", + .appleS7: "arm64e", + .appleS8: "arm64e", + .appleS9: "arm64e", + .appleS10: "arm64e" + ] + + // Itera sobre todos los casos de DeviceModel para verificar su arquitectura. + for model in DeviceModel.allCases { + let calculatedArchitecture = model.architecture + var expectedArchitecture: String? + + switch model { + case .iPod(let model): + expectedArchitecture = expectedArchitectures[model.processor] + case .iPhone(let model): + expectedArchitecture = expectedArchitectures[model.processor] + case .iPad(let model): + expectedArchitecture = expectedArchitectures[model.processor] + case .appleWatch(let model): + expectedArchitecture = expectedArchitectures[model.processor] + case .appleTV(let model): + expectedArchitecture = expectedArchitectures[model.processor] + case .mac(let model): + expectedArchitecture = expectedArchitectures[model.processor] + case .macCatalyst, .macDesignedForIpad: + expectedArchitecture = "arm64" + case .simulator(_, let arch): + expectedArchitecture = arch + case .unknown: + expectedArchitecture = nil + } + + #expect( + calculatedArchitecture == expectedArchitecture, + "Architecture mismatch for \(model.name). Expected \(String(describing: expectedArchitecture)), got \(String(describing: calculatedArchitecture))" + ) + } } @Test("Verifies architecture for special cases") From 9caa7aed46fb52f3063c31f88838052a8630d7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:50:36 +0200 Subject: [PATCH 06/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift b/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift index b3e46bf..a45b289 100644 --- a/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift +++ b/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift @@ -53,7 +53,7 @@ class AdditionalCoverageTests: XCTestCase { } func test_init_with_simulator_identifier() { - // Simula el entorno de un simulador + // Simulates simulator environment let originalEnv = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] setenv("SIMULATOR_MODEL_IDENTIFIER", "iPhone15,4", 1) // iPhone 15 From 2f6675ab6d8e7a55ec5b53477daffd83514c2e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:50:49 +0200 Subject: [PATCH 07/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../DeviceModelArchitectureTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift index 82f5edf..3826816 100644 --- a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift +++ b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift @@ -6,8 +6,8 @@ struct DeviceModelArchitectureTests { @Test("Verifies architecture for all device models") func testArchitectureForAllTypes() { - // Diccionario de referencia que mapea cada procesador a su arquitectura esperada. - // Esta es nuestra "fuente de la verdad" para el test. + // Reference dictionary that maps each processor to its expected architecture. + // This is our "source of truth" for the test. let expectedArchitectures: [DeviceModel.Processor: String] = [ // Early Processors .APL0098: "armv6", From bd7a193e2ee5dbb9cfd689155a8c3a9b63498951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:51:01 +0200 Subject: [PATCH 08/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../DeviceIdentificatorTests/DeviceModelArchitectureTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift index 3826816..a4310d2 100644 --- a/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift +++ b/Tests/DeviceIdentificatorTests/DeviceModelArchitectureTests.swift @@ -65,7 +65,7 @@ struct DeviceModelArchitectureTests { .appleS10: "arm64e" ] - // Itera sobre todos los casos de DeviceModel para verificar su arquitectura. + // Iterate over all DeviceModel cases to verify their architecture. for model in DeviceModel.allCases { let calculatedArchitecture = model.architecture var expectedArchitecture: String? From 3916e74e8fe512e82b67eebbc175e827732449b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:51:18 +0200 Subject: [PATCH 09/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../DeviceModelDeviceIdentifierTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift index 8e29a03..cc93ac8 100644 --- a/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift +++ b/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift @@ -23,7 +23,7 @@ struct DeviceModelDeviceIdentifierTests { @Test("Initialize from simulator identifier") func initWithSimulatorIdentifier() { - // Simula el entorno de un simulador + // Simulate the environment of a simulator let originalEnv = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] setenv("SIMULATOR_MODEL_IDENTIFIER", "iPhone15,4", 1) // iPhone 15 From 95bbb1bc6a2bd7b67c9af7f02a5c86e3155d4614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:52:02 +0200 Subject: [PATCH 10/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../DeviceModelDeviceIdentifierTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift index cc93ac8..9df7006 100644 --- a/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift +++ b/Tests/DeviceIdentificatorTests/DeviceModelDeviceIdentifierTests.swift @@ -31,7 +31,7 @@ struct DeviceModelDeviceIdentifierTests { let expectedModel = DeviceModel.simulator(.iPhone(.iPhone15), arch: "arm64") #expect(simulatorDevice == expectedModel) - // Limpia la variable de entorno + // Clean up environment variable if let originalEnv { setenv("SIMULATOR_MODEL_IDENTIFIER", originalEnv, 1) } else { From a148cb6b9457c4a2ab438b65370462cf766df608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:52:14 +0200 Subject: [PATCH 11/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Tests/DeviceIdentificatorTests/NewModelsTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DeviceIdentificatorTests/NewModelsTests.swift b/Tests/DeviceIdentificatorTests/NewModelsTests.swift index 995e9be..68ac166 100644 --- a/Tests/DeviceIdentificatorTests/NewModelsTests.swift +++ b/Tests/DeviceIdentificatorTests/NewModelsTests.swift @@ -71,7 +71,7 @@ struct NewModelsTests { #expect(air11WifiDevice.deviceIdentifier == "iPad15,3") #expect(air11Wifi.processor == .appleM3) #expect(DeviceModel(deviceIdentifier: "iPad15,3") == air11WifiDevice) - // ... (se pueden añadir el resto de variantes de Air M3 aquí) + // ... (additional Air M3 variants can be added here) } @Test("iPad Mini A17 Pro properties") From 188ef0500bbc3e236c25480da449bcb1439346b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:52:27 +0200 Subject: [PATCH 12/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift b/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift index a45b289..d2c278a 100644 --- a/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift +++ b/Tests/DeviceIdentificatorTests/AdditionalCoverageTests.swift @@ -65,7 +65,7 @@ class AdditionalCoverageTests: XCTestCase { XCTAssertTrue(simulatorDevice.isSimulator) XCTAssertTrue(simulatorDevice.isIphone) - // Limpia la variable de entorno + // Clean up environment variable if let originalEnv = originalEnv { setenv("SIMULATOR_MODEL_IDENTIFIER", originalEnv, 1) } else { From 618a376c359bcd6990c14bd7f5407f9e63483b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:52:39 +0200 Subject: [PATCH 13/15] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift b/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift index d37e4ae..edf58f1 100644 --- a/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift +++ b/Tests/DeviceIdentificatorTests/DeviceModelCurrentTests.swift @@ -19,8 +19,8 @@ struct DeviceModelCurrentTests { #expect(!current.isSimulator, "Should be identified as a real device.") #endif - // La siguiente prueba es un ejemplo y solo pasará si ejecutas los tests en un iPhone 15. - // El objetivo es demostrar que el valor es coherente. + // The following test is an example and will only pass if you run tests on an iPhone 15. + // The goal is to demonstrate that the value is consistent. // #expect(current == .iPhone(.iPhone15)) } } From 200e8c6147b88faded47e2fe68a5e91efdcd7099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:53:59 +0200 Subject: [PATCH 14/15] Update Sources/DeviceIdentificator/Models/IPadModel+Processor.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Sources/DeviceIdentificator/Models/IPadModel+Processor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift b/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift index 098e0f7..3511ef6 100644 --- a/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift +++ b/Sources/DeviceIdentificator/Models/IPadModel+Processor.swift @@ -14,7 +14,7 @@ public extension DeviceModel.IPadModel { case .gen8Wifi, .gen8Cellular: return .appleA12Bionic case .gen9Wifi, .gen9Cellular: return .appleA13Bionic case .gen10Wifi, .gen10Cellular: return .appleA14Bionic - case .gen11Wifi, .gen11Cellular: return .appleA14Bionic // Asumido, basado en el iPad 10 + case .gen11Wifi, .gen11Cellular: return .appleA14Bionic // Assumed, based on iPad 10 // Minis case .mini1Wifi, .mini1GSM, .mini1CDMA: return .appleA5 From 3a61e8e832b3ba58ecf469d3dc4e72f13433c3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Varela?= Date: Fri, 3 Oct 2025 17:54:39 +0200 Subject: [PATCH 15/15] Update Sources/DeviceIdentificator/Models/IPadModel+Name.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Sources/DeviceIdentificator/Models/IPadModel+Name.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/DeviceIdentificator/Models/IPadModel+Name.swift b/Sources/DeviceIdentificator/Models/IPadModel+Name.swift index 2d65615..0d8d074 100644 --- a/Sources/DeviceIdentificator/Models/IPadModel+Name.swift +++ b/Sources/DeviceIdentificator/Models/IPadModel+Name.swift @@ -64,7 +64,7 @@ public extension DeviceModel.IPadModel { case .air5Cellular: return "iPad Air 5 (Cellular)" case .air11InchM2Wifi: return "iPad Air M2 11\" (Cellular)" case .air11InchM2Cellular: return "iPad Air M2 11\" (Cellular)" - case .air13InchM2Wifi: return "iPad Air M2 13\" (Cellular)" + case .air13InchM2Wifi: return "iPad Air M2 13\" (Wifi)" case .air13InchM2Cellular: return "iPad Air M2 13\" (Cellular)" case .air11InchM3Wifi: return "iPad Air M3 11\" (Wifi)" case .air11InchM3Cellular: return "iPad Air M3 11\" (Cellular)"