diff --git a/src/mcp/tools/run-cloud-test.ts b/src/mcp/tools/run-cloud-test.ts index 38ae9c6..6801ed9 100644 --- a/src/mcp/tools/run-cloud-test.ts +++ b/src/mcp/tools/run-cloud-test.ts @@ -89,8 +89,8 @@ export function registerRunCloudTest(server: McpServer): void { .string() .optional() .describe('ID of a previously uploaded binary. Mutually exclusive with appFile.'), - iosVersion: z.string().optional().describe('iOS version, e.g. "17"'), - iosDevice: z.string().optional().describe('iOS device, e.g. "iphone-14"'), + iosVersion: z.string().optional().describe('iOS version, e.g. "26"'), + iosDevice: z.string().optional().describe('iOS device, e.g. "iphone-16"'), androidApiLevel: z.string().optional().describe('Android API level, e.g. "34"'), androidDevice: z.string().optional().describe('Android device, e.g. "pixel-10"'), googlePlay: z.boolean().optional().describe('Use a Google Play-enabled Android image'), diff --git a/src/services/device-validation.service.ts b/src/services/device-validation.service.ts index bdc1417..f3daace 100644 --- a/src/services/device-validation.service.ts +++ b/src/services/device-validation.service.ts @@ -155,8 +155,8 @@ export class DeviceValidationService { `[DEBUG] Supported iOS versions: ${supportedVersions.join(', ')}`, ], // Mirrors the API's global defaults, as for Android above. - defaultDevice: 'iphone-14', - defaultVersion: '17', + defaultDevice: 'iphone-16', + defaultVersion: '26', device: iOSDevice, deviceArg: argNames.iOSDevice, deviceKind: 'iOS', diff --git a/src/types/domain/device.types.ts b/src/types/domain/device.types.ts index 85ebbf4..a6ca9d2 100644 --- a/src/types/domain/device.types.ts +++ b/src/types/domain/device.types.ts @@ -14,15 +14,10 @@ */ export enum EiOSDevices { - 'ipad-pro-6th-gen' = 'ipad-pro-6th-gen', 'ipad-pro-m5-11' = 'ipad-pro-m5-11', 'ipad-pro-m5-13' = 'ipad-pro-m5-13', 'iphone-14' = 'iphone-14', - 'iphone-15' = 'iphone-15', 'iphone-16' = 'iphone-16', - 'iphone-16-plus' = 'iphone-16-plus', - 'iphone-16-pro' = 'iphone-16-pro', - 'iphone-16-pro-max' = 'iphone-16-pro-max', 'iphone-17' = 'iphone-17', 'iphone-18-pro' = 'iphone-18-pro', 'iphone-18-pro-max' = 'iphone-18-pro-max', @@ -44,7 +39,6 @@ export enum EAndroidDevices { export enum EiOSVersions { 'eighteen' = '18', - 'seventeen' = '17', 'twentySeven' = '27', 'twentySix' = '26', } diff --git a/test/integration/cloud.integration.test.ts b/test/integration/cloud.integration.test.ts index 08a7806..8453f5d 100644 --- a/test/integration/cloud.integration.test.ts +++ b/test/integration/cloud.integration.test.ts @@ -141,7 +141,7 @@ appId: com.example.app describe('device management path', () => { it('should accept valid iOS device configuration', async () => { - const command = `${CLI} cloud ${iosAppFile} ${testFlowFile} --api-key ${mockApiKey} --api-url ${mockApiUrl} --ios-device iphone-14 --ios-version 17 --async --json`; + const command = `${CLI} cloud ${iosAppFile} ${testFlowFile} --api-key ${mockApiKey} --api-url ${mockApiUrl} --ios-device iphone-14 --ios-version 18 --async --json`; const { stdout } = await exec(command, { timeout: 30_000 }); expectAsyncRunJson(stdout); @@ -175,10 +175,10 @@ appId: com.example.app }); it('asks for the version when a lone device needs a non-default one', async () => { - const command = `${CLI} cloud ${iosAppFile} ${testFlowFile} --api-key ${mockApiKey} --api-url ${mockApiUrl} --ios-device iphone-17 --dry-run`; + const command = `${CLI} cloud ${iosAppFile} ${testFlowFile} --api-key ${mockApiKey} --api-url ${mockApiUrl} --ios-device iphone-14 --dry-run`; const { output } = await runExpectingFailure(command); - expect(output).to.include('iphone-17 only supports these iOS versions'); + expect(output).to.include('iphone-14 only supports these iOS versions'); expect(output).to.include('--ios-version'); }); }); @@ -186,7 +186,7 @@ appId: com.example.app // #1105 device matrix: repeated --ios-device-matrix / --android-device-matrix cells. describe('device matrix', () => { it('accepts a repeated --ios-device-matrix matrix and still yields one upload', async () => { - const command = `${CLI} cloud ${iosAppFile} ${testFlowFile} --api-key ${mockApiKey} --api-url ${mockApiUrl} --ios-device-matrix iphone-16:18 --ios-device-matrix iphone-16-pro:26 --async --json`; + const command = `${CLI} cloud ${iosAppFile} ${testFlowFile} --api-key ${mockApiKey} --api-url ${mockApiUrl} --ios-device-matrix iphone-16:18 --ios-device-matrix iphone-17:26 --async --json`; const { stdout } = await exec(command, { timeout: 30_000 }); // Still one upload with one uploadId — the matrix is a property of the diff --git a/test/unit/device-matrix.test.ts b/test/unit/device-matrix.test.ts index 20476a1..bb8a5cd 100644 --- a/test/unit/device-matrix.test.ts +++ b/test/unit/device-matrix.test.ts @@ -20,12 +20,12 @@ describe('parseDeviceMatrix', () => { it('parses each --ios-device-matrix as exactly one cell (no cross-product)', () => { const matrix = parseDeviceMatrix( - ['iphone-16:18', 'iphone-16-pro:26'], + ['iphone-16:18', 'iphone-17:26'], [], ); expect(matrix).to.deep.equal([ { iOSDevice: 'iphone-16', iOSVersion: '18' }, - { iOSDevice: 'iphone-16-pro', iOSVersion: '26' }, + { iOSDevice: 'iphone-17', iOSVersion: '26' }, ]); expect(matrixIsIos(matrix)).to.equal(true); }); diff --git a/test/unit/device-validation.service.test.ts b/test/unit/device-validation.service.test.ts index 5f25e9f..51b8a7b 100644 --- a/test/unit/device-validation.service.test.ts +++ b/test/unit/device-validation.service.test.ts @@ -11,7 +11,8 @@ import type { CompatibilityData } from '../../src/utils/compatibility.js'; */ const compat: CompatibilityData = { ios: { - 'iphone-14': ['17', '18'], + 'iphone-14': ['18'], + 'iphone-16': ['18', '26', '27'], 'iphone-17': ['26', '27'], 'iphone-19': ['28'], // A rollout gate can leave a device with nothing bookable. @@ -65,14 +66,14 @@ describe('DeviceValidationService', () => { describe('unknown devices', () => { it('rejects an unknown iOS device, listing what the API offers in its order', () => { - expect(() => ios('17', 'iphone-99')).to.throw( - 'iOS device "iphone-99" is not supported. Supported iOS devices: iphone-14, iphone-17, iphone-19. See https://docs.devicecloud.dev/getting-started/devices-configuration', + expect(() => ios('26', 'iphone-99')).to.throw( + 'iOS device "iphone-99" is not supported. Supported iOS devices: iphone-14, iphone-16, iphone-17, iphone-19. See https://docs.devicecloud.dev/getting-started/devices-configuration', ); }); it('never offers a gated device, and treats it as unsupported', () => { - expect(() => ios('17', 'iphone-gated')).to.throw( - /iOS device "iphone-gated" is not supported\. Supported iOS devices: iphone-14, iphone-17, iphone-19\./, + expect(() => ios('26', 'iphone-gated')).to.throw( + /iOS device "iphone-gated" is not supported\. Supported iOS devices: iphone-14, iphone-16, iphone-17, iphone-19\./, ); }); @@ -95,14 +96,14 @@ describe('DeviceValidationService', () => { }); it('does not resolve a prototype member as a device', () => { - expect(() => ios('17', 'constructor')).to.throw( + expect(() => ios('26', 'constructor')).to.throw( /iOS device "constructor" is not supported/, ); }); it('still fails when the API sent no list at all, without an empty list', () => { const noIos = { ...compat, ios: {} }; - expect(() => ios('17', 'iphone-14', noIos)).to.throw( + expect(() => ios('18', 'iphone-14', noIos)).to.throw( 'iOS device "iphone-14" is not supported. See https://docs.devicecloud.dev/getting-started/devices-configuration', ); }); @@ -116,7 +117,7 @@ describe('DeviceValidationService', () => { it('rejects an unsupported explicit pair with the device\'s versions', () => { expect(() => ios('27', 'iphone-14')).to.throw( - /^iphone-14 only supports these iOS versions: 17, 18$/, + /^iphone-14 only supports these iOS versions: 18$/, ); expect(() => android('34', 'pixel-10')).to.throw( /^pixel-10 only supports these Android API levels: 36, 37$/, @@ -129,13 +130,13 @@ describe('DeviceValidationService', () => { }); }); - // The API fills an omitted half from the same global defaults (iphone-14 / - // iOS 17, pixel-10 / API 36) and rejects an incompatible pair, so the CLI + // The API fills an omitted half from the same global defaults (iphone-16 / + // iOS 26, pixel-10 / API 36) and rejects an incompatible pair, so the CLI // mirrors that — but must tell the user to pass the other half. describe('requests that rely on a default', () => { it('tells a device-only iOS request to pass the version explicitly', () => { - expect(() => ios(undefined, 'iphone-17')).to.throw( - 'iphone-17 only supports these iOS versions: 26, 27. No iOS version was given, so the default (17) was checked: pass one of those explicitly with --ios-version', + expect(() => ios(undefined, 'iphone-14')).to.throw( + 'iphone-14 only supports these iOS versions: 18. No iOS version was given, so the default (26) was checked: pass one of those explicitly with --ios-version', ); }); @@ -146,14 +147,14 @@ describe('DeviceValidationService', () => { }); it('accepts a device-only request when the default version fits', () => { - expect(() => ios(undefined, 'iphone-14')).to.not.throw(); + expect(() => ios(undefined, 'iphone-17')).to.not.throw(); expect(() => android(undefined, 'pixel-7')).to.not.throw(); expect(() => android(undefined, 'pixel-10')).to.not.throw(); }); it('names the MCP tool parameters when asked to', () => { expect(() => - service.validateiOSDevice(undefined, 'iphone-17', compat, { + service.validateiOSDevice(undefined, 'iphone-14', compat, { argNames: MCP_ARG_NAMES, }), ).to.throw(/pass one of those explicitly with iosVersion$/); @@ -165,14 +166,14 @@ describe('DeviceValidationService', () => { }); it('points a version-only request at the devices that offer that version', () => { - expect(() => ios('27')).to.throw( - 'iphone-14 only supports these iOS versions: 17, 18. No iOS device was given, so the default (iphone-14) was checked: pass one that offers iOS 27 with --ios-device: iphone-17', + expect(() => ios('28')).to.throw( + 'iphone-16 only supports these iOS versions: 18, 26, 27. No iOS device was given, so the default (iphone-16) was checked: pass one that offers iOS 28 with --ios-device: iphone-19', ); }); it('says when no device offers the requested version at all', () => { expect(() => ios('99')).to.throw( - /No iOS device was given, so the default \(iphone-14\) was checked: no iOS device offers iOS 99$/, + /No iOS device was given, so the default \(iphone-16\) was checked: no iOS device offers iOS 99$/, ); // The default device (pixel-10) has Play images, as it does in the API. const playDefault = {