Skip to content

Commit 29d96e0

Browse files
author
wan
committed
feat: HBuilderX 可视化窗口,选择iOS测试,支持iOS真机
1 parent 18517a9 commit 29d96e0

13 files changed

Lines changed: 239 additions & 65 deletions

package.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
},
7878
{
7979
"command": "unitest.runTestIOS",
80-
"title": "运行测试到ios模拟器"
80+
"title": "运行测试到ios"
8181
},
8282
{
8383
"command": "unitest.runTestAndroid",
@@ -575,7 +575,7 @@
575575
},
576576
{
577577
"command": "unitest.runTestIOS",
578-
"title": "iOS模拟器(&I)",
578+
"title": "iOS(&I)",
579579
"when": "isMac",
580580
"group": "unitest@2"
581581
},
@@ -640,7 +640,7 @@
640640
},
641641
{
642642
"command": "unitest.runCurrentTestIOS",
643-
"title": "iOS模拟器(&I)",
643+
"title": "iOS(&I)",
644644
"when": "isMac",
645645
"group": "unitestForCurrent@2"
646646
},
@@ -710,7 +710,7 @@
710710
},
711711
{
712712
"command": "unitest.runCurrentTestIOS",
713-
"title": "iOS模拟器(&I)",
713+
"title": "iOS(&I)",
714714
"when": "isMac",
715715
"group": "unitestForCurrent@2"
716716
},
@@ -838,5 +838,8 @@
838838
},
839839
"keywords": [
840840
"uni-app,test,自动化测试"
841-
]
841+
],
842+
"dependencies": {
843+
"adm-zip": "^0.5.17"
844+
}
842845
}

src/HBuilderXCli.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ const {
3535
getFileNameForDate
3636
} = require('./utils/utils_files.js');
3737

38-
const editEnvjsFile = require('./core/edit_env_js_file.js');
38+
const {
39+
editEnvjsFile, loadEnvConfig
40+
} = require('./core/edit_env_js_file.js');
3941
const { modifyJestConfigJSFile } = require('./core/edit_jest_config_js_file.js');
4042

4143
const Initialize = require('./Initialize.js');

src/TestCaseRun.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const cmpVerionForH5 = compareHBuilderXVersions(hxVersionForDiff, '3.2.10');
1717
let config = require('./core/config.js');
1818

1919
const getProjectUnicloudData = require("./core/get_project_unicloud_data.js");
20+
const IOSDeviceHelper = require('./core/ios_device_helper.js');
2021
const {
2122
isUniAppCli,
2223
isUniAppX,
@@ -28,7 +29,8 @@ const {
2829
checkCustomTestEnvironmentDependency,
2930
checkUtsProject,
3031
readUniappManifestJson,
31-
uniapp_x_is_vapor
32+
uniapp_x_is_vapor,
33+
get_ios_device_type
3234
} = require('./core/core.js');
3335

3436
const {
@@ -40,7 +42,9 @@ const {
4042
getFileNameForDate
4143
} = require('./utils/utils_files.js');
4244

43-
const editEnvjsFile = require('./core/edit_env_js_file.js');
45+
const {
46+
editEnvjsFile
47+
} = require('./core/edit_env_js_file.js');
4448
const { modifyJestConfigJSFile } = require('./core/edit_jest_config_js_file.js');
4549

4650
const Initialize = require('./Initialize.js');
@@ -527,11 +531,23 @@ class RunTest extends Common {
527531
maxBuffer: 2000 * 1024
528532
};
529533

530-
// 蒸汽模式:依据项目mainfest.json
531-
// let isVapor = await uniapp_x_is_vapor(this.projectPath, is_uniapp_cli);
532-
// if (typeof isVapor === 'boolean' && isVapor) {
533-
// cmdOpts["env"]["UNI_APP_X_DOM2"] = true;
534-
// };
534+
// 2026-04 需求:ios需要支持真机 gml要求传递参数 HX_USE_BASE_TYPE
535+
if (testPlatform == "ios") {
536+
let test_device_type = await get_ios_device_type(deviceId);
537+
console.log("test_device_type =>", test_device_type);
538+
if (test_device_type == "真机") {
539+
const iosHelper = new IOSDeviceHelper();
540+
let ipa_path = await iosHelper.get_ios_ipa_path(is_uniapp_x, UNI_APP_X_DOM2, this.UNI_AUTOMATOR_CONFIG);
541+
cmdOpts.env.HX_USE_BASE_TYPE = await iosHelper.get_hx_use_base_type(this.UNI_AUTOMATOR_CONFIG);
542+
cmdOpts.env.IOS_RUNTIME_NASE_PATH = ipa_path;
543+
544+
const _utsBaseInfo = await iosHelper.get_uts_base_info(is_uniapp_x, ipa_path);
545+
cmdOpts.env.UTS_BASE_INFO = _utsBaseInfo ? JSON.stringify(_utsBaseInfo) : '';
546+
if (_utsBaseInfo == null) {
547+
createOutputChannel(`[iOS真机测试] 未能从IPA包中读取到UTS基础信息,可能会导致测试运行异常,请检查!`, 'warning');
548+
};
549+
};
550+
};
535551

536552
// 蒸汽模式:设备选择窗口的配置设置
537553
if (UNI_APP_X_DOM2 === true) {
@@ -820,7 +836,10 @@ class RunTest extends Common {
820836
"is_uniapp_cli": is_uniapp_cli
821837
};
822838
let changeResult = await modifyJestConfigJSFile(scope, proj);
823-
if (changeResult == false) return;
839+
if (changeResult == false) {
840+
logger("修改测试范围失败,测试中止。");
841+
return;
842+
};
824843

825844
// 注意:以前叫h5, 后来uni-app x要求改名为web。为了兼容以前的命令行参数,虽然入参是web,但是转化为h5。
826845
switch (argv_uniPlatform) {

src/core/config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,18 @@ const HBuilderX_NPM_PATH = path.join(hx.env.appRoot, "plugins", "npm", "npm");
2020
const LAUNCHER_PATH = path.join(hx.env.appRoot, "plugins", "launcher");
2121
const LAUNCHER_ANDROID = path.join(LAUNCHER_PATH, "base/android_base.apk");
2222
const LAUNCHER_IOS = path.join(LAUNCHER_PATH, "base/Pandora_simulator.app");
23+
const LAUNCHER_IOS_IPA = path.join(LAUNCHER_PATH, "base/iPhone_base.ipa");
2324
const LAUNCHER_VERSION_TXT = path.join(LAUNCHER_PATH, "base", "version.txt");
2425

2526
const UNIAPP_X_LAUNCHER_PATH = path.join(hx.env.appRoot, "plugins", "uniappx-launcher");
2627
const UNIAPP_X_LAUNCHER_IOS = path.join(UNIAPP_X_LAUNCHER_PATH, "base/Pandora_simulator.app");
28+
const UNIAPP_X_LAUNCHER_IOS_IPA = path.join(UNIAPP_X_LAUNCHER_PATH, "base/iPhone_base.ipa");
2729
const UNIAPP_X_LAUNCHER_ANDROID = path.join(UNIAPP_X_LAUNCHER_PATH, "base/android_base.apk");
2830
const UNIAPP_X_LAUNCHER_VERSION_TXT = path.join(UNIAPP_X_LAUNCHER_PATH, "base", "version.txt");
2931

3032
const UNIAPP_X_VAPOR_LAUNCHER_PATH = path.join(hx.env.appRoot, "plugins", "uniappx-vapor-launcher");
3133
const UNIAPP_X_VAPOR_LAUNCHER_IOS = path.join(UNIAPP_X_VAPOR_LAUNCHER_PATH, "base/Pandora_simulator.app");
34+
const UNIAPP_X_VAPOR_LAUNCHER_IOS_IPA = path.join(UNIAPP_X_VAPOR_LAUNCHER_PATH, "base/iPhone_base.ipa");
3235
const UNIAPP_X_VAPOR_LAUNCHER_ANDROID = path.join(UNIAPP_X_VAPOR_LAUNCHER_PATH, "base/android_base.apk");
3336
const UNIAPP_X_VAPOR_LAUNCHER_VERSION_TXT = path.join(UNIAPP_X_VAPOR_LAUNCHER_PATH, "base", "version.txt");
3437

@@ -85,16 +88,19 @@ module.exports = {
8588
LAUNCHER_PATH,
8689
LAUNCHER_ANDROID,
8790
LAUNCHER_IOS,
91+
LAUNCHER_IOS_IPA,
8892
LAUNCHER_VERSION_TXT,
8993

9094
UNIAPP_X_LAUNCHER_PATH,
9195
UNIAPP_X_LAUNCHER_ANDROID,
9296
UNIAPP_X_LAUNCHER_IOS,
97+
UNIAPP_X_LAUNCHER_IOS_IPA,
9398
UNIAPP_X_LAUNCHER_VERSION_TXT,
9499

95100
UNIAPP_X_VAPOR_LAUNCHER_PATH,
96101
UNIAPP_X_VAPOR_LAUNCHER_ANDROID,
97102
UNIAPP_X_VAPOR_LAUNCHER_IOS,
103+
UNIAPP_X_VAPOR_LAUNCHER_IOS_IPA,
98104
UNIAPP_X_VAPOR_LAUNCHER_VERSION_TXT,
99105

100106
UNI_CLI_PATH,

src/core/core.js

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -584,19 +584,42 @@ async function readUniappManifestJson(project_path, is_uniapp_cli, field) {
584584
});
585585
return result;
586586
};
587-
588-
/**
589-
* @description 获取项目是否是vapor
590-
*/
591-
async function uniapp_x_is_vapor(projectPath, is_uniapp_cli=false) {
592-
try {
593-
let fdata = await readUniappManifestJson(projectPath, is_uniapp_cli, "uni-app-x");
594-
let { data } = fdata;
595-
return data["vapor"];
596-
} catch (error) {
597-
return false
598-
}
599-
};
587+
588+
/**
589+
* @description 获取项目是否是vapor
590+
*/
591+
async function uniapp_x_is_vapor(projectPath, is_uniapp_cli=false) {
592+
try {
593+
let fdata = await readUniappManifestJson(projectPath, is_uniapp_cli, "uni-app-x");
594+
let { data } = fdata;
595+
return data["vapor"];
596+
} catch (error) {
597+
return false
598+
}
599+
};
600+
601+
602+
/**
603+
* @description 获取ios设备类型: 真机 | 模拟器
604+
* @param {Object} deviceId
605+
*/
606+
async function get_ios_device_type(deviceId) {
607+
let test_device_type = "";
608+
try {
609+
let device_result = global.global_devicesList;
610+
let ios_sim_list = device_result.ios_simulator ? device_result?.ios_simulator : [];
611+
let ios_phone_list = device_result.ios_phone ? device_result?.ios_phone : [];
612+
let ios_list = [...ios_phone_list, ...ios_sim_list];
613+
for (let s of ios_list) {
614+
if (s.udid == deviceId) {
615+
test_device_type = s.device_type;
616+
break;
617+
};
618+
};
619+
} catch (error) {};
620+
return test_device_type;
621+
};
622+
600623

601624
module.exports = {
602625
getPluginConfig,
@@ -612,6 +635,7 @@ module.exports = {
612635
installTerminal,
613636
checkCustomTestEnvironmentDependency,
614637
checkUtsProject,
615-
readUniappManifestJson,
616-
uniapp_x_is_vapor
638+
readUniappManifestJson,
639+
uniapp_x_is_vapor,
640+
get_ios_device_type
617641
};

src/core/edit_env_js_file.js

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ const hx = require('hbuilderx');
33
let config = require('./config.js');
44
const {
55
createOutputChannel,
6-
getPluginConfig
6+
getPluginConfig,
7+
get_ios_device_type
78
} = require('./core.js');
89

910
const {
@@ -53,16 +54,20 @@ function loadEnvConfig(envJsPath) {
5354
* @param {Object} envjs - env.js配置对象
5455
* @returns {Promise<String>} 启动器路径
5556
*/
56-
async function getLauncherPath(testPlatform, isUniappX, isVapor, envjs) {
57+
async function getLauncherPath(testPlatform, isUniappX, isVapor, envjs, test_device_type="") {
58+
// console.error("[test_device_type] = ", test_device_type);
59+
const isIOSRealDevice = testPlatform === PLATFORM.IOS && test_device_type === "真机";
60+
5761
const launcherConfig = {
5862
[PLATFORM.ANDROID]: {
5963
uniappX: isVapor ? config.UNIAPP_X_VAPOR_LAUNCHER_ANDROID : config.UNIAPP_X_LAUNCHER_ANDROID,
6064
normal: config.LAUNCHER_ANDROID
6165
},
62-
// ios真机、模拟器,所需的文件不一样。由于uni-app测试框架不支持ios真机。这里暂不区分。
6366
[PLATFORM.IOS]: {
64-
uniappX: isVapor ? config.UNIAPP_X_VAPOR_LAUNCHER_IOS : config.UNIAPP_X_LAUNCHER_IOS,
65-
normal: config.LAUNCHER_IOS
67+
uniappX: isIOSRealDevice
68+
? (isVapor ? config.UNIAPP_X_VAPOR_LAUNCHER_IOS_IPA : config.UNIAPP_X_LAUNCHER_IOS_IPA)
69+
: (isVapor ? config.UNIAPP_X_VAPOR_LAUNCHER_IOS : config.UNIAPP_X_LAUNCHER_IOS),
70+
normal: isIOSRealDevice ? config.LAUNCHER_IOS_IPA : config.LAUNCHER_IOS
6671
}
6772
};
6873

@@ -127,13 +132,13 @@ function getPlatformConfigNode(envjs, isUniappX) {
127132
function updateVersionInfo(envjs, isUniappX, isVapor) {
128133
if (!envjs['app-plus']) {
129134
envjs['app-plus'] = {};
130-
};
131-
let versionTxtFile = config.LAUNCHER_VERSION_TXT;
132-
if (isUniappX) {
133-
versionTxtFile = config.UNIAPP_X_LAUNCHER_VERSION_TXT;
134-
};
135-
if (isVapor) {
136-
versionTxtFile = config.UNIAPP_X_VAPOR_LAUNCHER_VERSION_TXT;
135+
};
136+
let versionTxtFile = config.LAUNCHER_VERSION_TXT;
137+
if (isUniappX) {
138+
versionTxtFile = config.UNIAPP_X_LAUNCHER_VERSION_TXT;
139+
};
140+
if (isVapor) {
141+
versionTxtFile = config.UNIAPP_X_VAPOR_LAUNCHER_VERSION_TXT;
137142
};
138143
if (isUniappX) {
139144
const oldVersionTxtFile = envjs['app-plus']?.['uni-app-x']?.version;
@@ -221,7 +226,8 @@ async function handleWeixinPlatform(envjs, envJsPath, logger) {
221226
return false;
222227
}
223228
return true;
224-
}
229+
};
230+
225231

226232
/**
227233
* @description 修改测试配置文件env.js, ios和android测试需要在env.js指定设备ID
@@ -235,17 +241,22 @@ async function handleWeixinPlatform(envjs, envJsPath, logger) {
235241
* @returns {Promise<Boolean>} - 修改成功返回true,失败返回false
236242
*/
237243
async function editEnvjsFile(envJsPath = "", testPlatform = "", deviceId = "", uniProjectAttributeData = {}, terminalId) {
238-
const {
239-
is_uniapp_x: isUniappX,
240-
is_uniapp_x_vapor: isVapor
241-
} = uniProjectAttributeData;
242-
console.error("isVapor = ", isVapor);
244+
const {
245+
is_uniapp_x: isUniappX,
246+
is_uniapp_x_vapor: isVapor
247+
} = uniProjectAttributeData;
248+
console.error("isVapor = ", isVapor);
243249

244250
const logger = createLogger(terminalId);
245-
246251
if (terminalId) {
247252
await logger(`[uniapp.test] 修改测试配置文件: ${envJsPath}`);
248-
}
253+
};
254+
255+
// 设备类型 模拟器、真机。目前只有ios平台需要
256+
let test_device_type = "";
257+
if (testPlatform == "ios") {
258+
test_device_type = await get_ios_device_type(deviceId);
259+
};
249260

250261
let envJsFileData = loadEnvConfig(envJsPath);
251262
if (!envJsFileData) {
@@ -263,7 +274,7 @@ async function editEnvjsFile(envJsPath = "", testPlatform = "", deviceId = "", u
263274
return await handleWeixinPlatform(envJsFileData, envJsPath, logger);
264275
};
265276

266-
const launcherPath = await getLauncherPath(testPlatform, isUniappX, isVapor, envJsFileData);
277+
const launcherPath = await getLauncherPath(testPlatform, isUniappX, isVapor, envJsFileData, test_device_type);
267278
console.log("[env.js]launcherPath = ", launcherPath)
268279
const isCustomRuntime = envJsFileData["is-custom-runtime"];
269280

@@ -288,4 +299,7 @@ async function editEnvjsFile(envJsPath = "", testPlatform = "", deviceId = "", u
288299
return true;
289300
};
290301

291-
module.exports = editEnvjsFile;
302+
module.exports = {
303+
editEnvjsFile,
304+
loadEnvConfig
305+
};

0 commit comments

Comments
 (0)