1/* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16const { spawn } = require('child_process'); 17const path = require('path'); 18const { 19 recursiveCreateFolders, 20 copyFile, 21 isExistFile, 22 writeFile, 23 readDir 24} = require("../utils/file.js"); 25 26 27const { writeJsonFile } = require("../utils/file"); 28 29 30module.exports = { test, runHvigor }; 31let origin = 40001; 32 33async function test(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath) { 34 return new Promise(async (resolve, reject) => { 35 const testCasePath = `${casePath}\\test\\component_test\\test_cases\\components\\${testFile[0]}`; 36 const previewerExePath = `${sdkPath}\\previewer\\common\\bin`; 37 const jParam = `${testCasePath}\\entry\\.preview\\default\\intermediates\\loader_out\\default\\ets`; 38 const ljPathParam = `${testCasePath}\\entry\\.preview\\default\\intermediates\\loader\\default\\loader.json`; 39 const fParam = `${testCasePath}\\.idea\\previewer\\default\\defaultSettingConfig_Default.json`; 40 const arpParam = `${testCasePath}\\entry\\.preview\\default\\intermediates\\res\\default`; 41 const urlWithets = `"pages/${testFile[1]}/${testFile[2]}"`; 42 const urlParam = urlWithets.split(".ets")[0] + "\""; 43 let lwsParam = ++origin; 44 const page = `${testFile[0]}\\${testFile[1]}`.replaceAll("\\", "\\\\"); 45 const out = `${resultPath}\\${testFile[1]}\\${testFile[2]}.json`.replaceAll("\\", "\\\\"); 46 const componentTestParam = `{\\\"page\\\":\\\"${page}\\\",\\\"out\\\":\\\"${out}\\\"}`; 47 runPreviewer(previewerExePath, jParam, ljPathParam, fParam, urlParam, arpParam, 48 lwsParam, componentTestParam) 49 .then((isOver, error) => { 50 if (error) { 51 reject(error); 52 } else { 53 resolve(testFile); 54 } 55 }).catch((err) => { 56 if (err) { 57 throw err; 58 } 59 }); 60 }); 61} 62 63const runCommand = (command, args, options) => { 64 return new Promise((resolve, reject) => { 65 const child = spawn(command, args, { shell: true, ...options }); 66 if (!child) { 67 reject(new Error("Failed to create child process")); 68 return; 69 } 70 let stdoutData = ""; 71 let stderrData = ""; 72 child.stdout.on('data', data => { 73 stdoutData += data.toString(); 74 }); 75 child.stderr.on('data', (data) => { 76 stderrData += data.toString(); 77 if (data.toString().includes("ERROR")) { 78 resolve(false) 79 } 80 }); 81 child.on('close', code => { 82 if (code === 0) { 83 resolve(true); 84 } else { 85 resolve(false); 86 } 87 }); 88 }); 89}; 90 91async function runHvigor(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath) { 92 const testCasePath = `${casePath}\\test\\component_test\\test_cases\\components\\${testFile[0]}`; 93 const fParam = `${testCasePath}\\.idea\\previewer\\default\\defaultSettingConfig_Default.json`; 94 const caseResultPath = `${resultPath}\\${testFile[2]}.json`.replaceAll("\\", "\\\\"); 95 runCommand(`"${ohpmBat}"`, [ 96 'install', 97 '--all', 98 '--registry', 99 'https://ohpm.openharmony.cn/ohpm/', 100 '--strict_ssl', 101 'true' 102 ], { cwd: testCasePath }) 103 .then(async (isOk, err) => { 104 if (err) { 105 console.error(err); 106 } 107 if (!isOk) { 108 writeJsonFile("", caseResultPath) 109 .catch(err => { 110 reject(err); 111 }); 112 resolve(true); 113 } 114 }); 115 116 const localProperties = path.join(testCasePath, "local.properties"); 117 if (!await isExistFile(localProperties)) { 118 let sdkDir = sdkPath.replaceAll("\\", "/"); 119 let removeLast = sdkDir.replace(/\/\d+$/, ''); 120 let fileContext = `sdk.dir=${removeLast}`; 121 await writeFile(path.join(testCasePath, "local.properties"), fileContext); 122 } 123 124 await runCommand(`"${nodePath}"`, [ 125 `"${hvigorPath}"`, 126 '--sync', 127 '-p', 'product=default', 128 '--analyze=normal', 129 '--parallel', 130 '--incremental', 131 '--daemon' 132 ], { cwd: testCasePath }) 133 .then((isOk, err) => { 134 if (err) { 135 reject(err); 136 } 137 if (!isOk) { 138 writeJsonFile("", caseResultPath) 139 .catch(err => { 140 reject(err); 141 }); 142 resolve(true); 143 } 144 }); 145 146 await runCommand(`"${nodePath}"`, [ 147 `"${hvigorPath}"`, 148 '--mode', 'module', 149 '-p', 'module=entry@default', 150 '-p', 'product=default', 151 '-p', 'pageType=page', 152 '-p', 'compileResInc=true', 153 '-p', 'requiredDeviceType=default', 154 '-p', 'previewMode=true', 155 '-p', 'buildRoot=.preview', 156 'PreviewBuild', 157 '--watch', 158 '--analyze=normal', 159 '--parallel', 160 '--incremental', 161 '--daemon' 162 ], { cwd: testCasePath, shell: true }) 163 .then((isOk, err) => { 164 if (err) { 165 reject(err); 166 } 167 if (!isOk) { 168 writeJsonFile("", caseResultPath) 169 .catch(err => { 170 reject(err); 171 }); 172 resolve(true); 173 } 174 }); 175 176 await recursiveCreateFolders(fParam.split("\\defaultSettingConfig_Default.json")[0]); 177 const configFileExists = await isExistFile(fParam); 178 if (!configFileExists) { 179 await copyFile("previewer_host\\resource\\defaultSettingConfig_Default.json", fParam); 180 } 181} 182async function runPreviewer( 183 previewerExePath, jParam, ljPathParam, fParam, urlParam, arpParam, lwsParam, componentTestParam) { 184 return new Promise(async (resolve, reject) => { 185 const previewerProcess = spawn("Previewer.exe", [ 186 '-refresh', 'region', 187 '-projectID', '908375455', 188 '-ts', 'trace_48336_commandPipe', 189 '-j', jParam, 190 '-s', 'default_1713408574374_1', 191 '-cpm', 'false', 192 '-device', 'phone', 193 '-shape', 'rect', 194 '-sd', '480', 195 '-ljPath', `"${ljPathParam}"`, 196 '-or', '1080', '2340', 197 '-cr', '1080', '2340', 198 '-f', `"${fParam}"`, 199 '-n', '"entry"', 200 '-av', '"ACE_2_0"', 201 '-url', `${urlParam}`, 202 '-pages', '"main_pages"', 203 '-arp', `"${arpParam}"`, 204 '-pm', '"Stage"', 205 '-l', 'zh_CN', 206 '-cm', 'light', 207 '-o', 'portrait', 208 '-lws', lwsParam, 209 '-componentTest', `"${componentTestParam}"` 210 ], { detached: true, cwd: previewerExePath, shell: true }); 211 previewerProcess.on('close', (code) => { 212 resolve(true); 213 }); 214 previewerProcess.on('error', (err) => { 215 reject(err); 216 }); 217 }); 218}