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 to 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 */ 15import path from 'path'; 16import fs from 'fs'; 17import mocha from 'mocha'; 18import sinon from 'sinon'; 19import { expect } from 'chai'; 20 21import { 22 BUILD_ON, 23 JSBUNDLE, 24} from '../../lib/pre_define'; 25import { 26 resetComponentCollection, 27 componentCollection 28} from '../../lib/validate_ui_syntax'; 29import { 30 transformLog 31} from '../../lib/process_ui_syntax'; 32import { 33 componentInfo, 34 resetUtils, 35 storedFileInfo 36} from '../../lib/utils'; 37import main, { 38 partialUpdateConfig, 39 projectConfig, 40 readAppResource, 41 resetGlobalProgram, 42 resetMain, 43 resources, 44 sdkConfigs, 45 systemModules 46} from '../../main'; 47import { 48 etsChecker 49} from '../../lib/fast_build/ets_ui/rollup-plugin-ets-checker'; 50import { 51 etsTransform 52} from '../../lib/fast_build/ets_ui/rollup-plugin-ets-typescript'; 53import processStructComponentV2 from '../../lib/process_struct_componentV2'; 54import { 55 RollUpPluginMock 56} from './helpers/mockRollupContext'; 57import { 58 PartialUpdateConfig, 59 ProjectConfig 60} from './helpers/projectConfig'; 61import { 62 UT_VALIDATE_PAGES, 63 UT_VALIDATE_PAGES_JSBUNDLE, 64 UT_VALIDATE_PAGES_PREVIEW 65} from './helpers/pathConfig'; 66import { 67 parseFileNameFromPath, 68 parseLog, 69 processExecInStr, 70 sourceReplace 71} from './helpers/parser'; 72import { 73 scanFileNames 74} from './helpers/utils'; 75import { 76 Logger, 77 LogInfo 78} from './helpers/logger'; 79import { 80 ARKUI_SUBSYSTEM_CODE, 81 TSC_SYSTEM_CODE 82} from './helpers/common'; 83 84const PROJECT_ROOT: string = path.resolve(__dirname, '../../test/transform_ut'); 85const DEFAULT_PROJECT: string = 'application'; 86const TEST_CASES_PATH: string = path.resolve(PROJECT_ROOT, DEFAULT_PROJECT, 'entry/src/main/ets/pages'); 87const SYS_CONFIG_PATH: string = path.resolve(PROJECT_ROOT, DEFAULT_PROJECT, 'entry/src/main/ets/test/common'); 88const ERROR_COLLECTION_PATH: string = path.resolve(__dirname, '../../test/transform_ut_error.json'); 89const MAIN_PAGES: string[] = [ 90 ...UT_VALIDATE_PAGES, 91 ...UT_VALIDATE_PAGES_PREVIEW, 92 ...UT_VALIDATE_PAGES_JSBUNDLE 93].map((p) => `pages/utForValidate/${p}`); 94 95const systemModuleSet: Set<string> = new Set(); 96scanFileNames(SYS_CONFIG_PATH, systemModuleSet); 97 98mocha.describe('test UT for validate testcases [non-preview mode]', function () { 99 this.timeout(10000); 100 101 mocha.before(function () { 102 resetUtils(); 103 resetGlobalProgram(); 104 resetMain(); 105 this.rollup = new RollUpPluginMock(); 106 this.rollup.build(PROJECT_ROOT, DEFAULT_PROJECT, MAIN_PAGES); 107 108 // enable logger for etsTransform roll-up plugin 109 this.rollup.share.flushLogger(); 110 this.rollup.share.setEnableLogger(true); 111 this.rollup.share.setAllowedLoggerPrefix(['etsTransform', TSC_SYSTEM_CODE, ARKUI_SUBSYSTEM_CODE]); 112 113 this.globalProjectConfig = new ProjectConfig(); 114 this.globalProjectConfig.setPreview(false); 115 this.globalProjectConfig.setIgnoreWarning(true); 116 this.globalProjectConfig.scan(PROJECT_ROOT, DEFAULT_PROJECT, MAIN_PAGES); 117 this.globalProjectConfig.mockCompileContextInfo(`${PROJECT_ROOT}/${DEFAULT_PROJECT}`, MAIN_PAGES); 118 this.globalProjectConfig.concat(RollUpPluginMock.mockArkProjectConfig(PROJECT_ROOT, DEFAULT_PROJECT, false)); 119 120 this.rollup.share.projectConfig.concat(this.globalProjectConfig); 121 Object.assign(projectConfig, this.globalProjectConfig); 122 readAppResource(projectConfig.appResource); 123 124 this.globalPartialUpdateConfig = new PartialUpdateConfig(); 125 this.globalPartialUpdateConfig.setPartialUpdateMode(true); 126 this.globalPartialUpdateConfig.mockDisableArkTSLinter(); 127 Object.assign(partialUpdateConfig, this.globalPartialUpdateConfig); 128 129 Object.assign(main, { 130 sdkConfigs: [ 131 ...sdkConfigs 132 .filter((sdkConfig) => !sdkConfig['apiPath'].includes(SYS_CONFIG_PATH)) 133 .map((sdkConfig) => { 134 sdkConfig['apiPath'].push(SYS_CONFIG_PATH); 135 return sdkConfig; 136 } 137 ), 138 ], 139 systemModules: [...systemModules, ...systemModuleSet] 140 }); 141 142 this.etsCheckerPlugin = etsChecker(); 143 this.etsTransformPlugin = etsTransform(); 144 145 // disable writing to local files 146 sinon.stub(fs, 'writeSync'); 147 148 // run etsChecker once 149 const buildStart = this.etsCheckerPlugin.buildStart.bind(this.rollup); 150 buildStart(); 151 }); 152 153 mocha.after(() => { 154 this.rollup?.share?.flushLogger(); 155 delete this.rollup; 156 delete this.globalProjectConfig; 157 delete this.globalPartialUpdateConfig; 158 delete this.etsCheckerPlugin; 159 delete this.etsTransformPlugin; 160 161 resetUtils(); 162 resetGlobalProgram(); 163 resetMain(); 164 sinon.restore(); 165 }); 166 167 mocha.beforeEach(function () { 168 resources.app["media"] = {icon:16777222}; 169 resources.app["font"] = {song:16777223}; 170 171 process.env.rawFileResource = './'; 172 process.env.compileMode = 'moduleJson'; 173 process.env.compiler = BUILD_ON; 174 process.env.compileTool = 'rollup'; 175 176 transformLog.errors = []; 177 componentInfo.id = 0; 178 componentCollection.customComponents.clear(); 179 resetComponentCollection(); 180 storedFileInfo.setCurrentArkTsFile(); 181 182 // disable ignoreWarning to get log info 183 Object.assign(projectConfig, { ignoreWarning: false }); 184 }); 185 186 mocha.afterEach(function () { 187 this.rollup?.share?.flushLogger(); 188 processStructComponentV2.resetStructMapInEts(); 189 }); 190 191 [...UT_VALIDATE_PAGES, ...UT_VALIDATE_PAGES_JSBUNDLE].forEach((utPage, index) => { 192 mocha.it(`1-${index + 1}: test ${utPage}`, function (done) { 193 if (UT_VALIDATE_PAGES_JSBUNDLE.includes(utPage)) { 194 Object.assign(projectConfig, { compileMode: JSBUNDLE }); 195 } 196 197 const sourceFilePath: string = path.resolve(TEST_CASES_PATH, `utForValidate/${utPage}.ets`); 198 const sourceCode: string = fs.readFileSync(sourceFilePath, 'utf-8'); 199 200 storedFileInfo.addFileCacheInfo(sourceFilePath); 201 202 const transform = this.etsTransformPlugin.transform.bind(this.rollup); 203 const errorCollection: object = JSON.parse(fs.readFileSync(ERROR_COLLECTION_PATH, 'utf-8')); 204 const errorKey: string = parseFileNameFromPath(sourceFilePath); 205 const errorVals: object = errorCollection[errorKey] ?? {}; 206 207 const expectResults: LogInfo[] = Array.isArray(errorVals) ? errorVals : [errorVals]; 208 209 let expectErrorInfos: LogInfo[] = []; 210 let expectWarnInfos: LogInfo[] = []; 211 expectResults.filter(e => e.type).forEach((e) => { 212 if (e.type === 'ERROR') { 213 expectErrorInfos.push({ ...e, message: processExecInStr(e.message.trim()) }); 214 } else { 215 expectWarnInfos.push({ ...e, message: processExecInStr(e.message.trim()) }); 216 } 217 }); 218 219 transform(sourceReplace(sourceCode), sourceFilePath) 220 .then(_ => { 221 const logger: Logger = Logger.mergeLoggers( 222 'etsTransform', 223 TSC_SYSTEM_CODE, 224 ARKUI_SUBSYSTEM_CODE 225 ); 226 227 const errorInfos: LogInfo[] = logger.getErrorInfos(); 228 const warnInfos: LogInfo[] = logger.getWarnInfos(); 229 230 expect(errorInfos.length === expectErrorInfos.length).to.be.true; 231 expect(warnInfos.length === expectWarnInfos.length).to.be.true; 232 233 let _findIndex: number = 0; 234 let _sumCount: number = expectErrorInfos.length; 235 errorInfos.forEach((err) => { 236 const message: string = parseLog(err.cause ?? err.message); 237 const findIndex: number = expectErrorInfos 238 .slice(_findIndex) 239 .findIndex((value) => value.message === message); 240 expect(findIndex !== -1).to.be.true; 241 if (err.code) { 242 expect(expectErrorInfos[_findIndex + findIndex].code === err.code).to.be.true; 243 expect(expectErrorInfos[_findIndex + findIndex].solutions ?? []).to.deep.equal(err.solutions ?? []); 244 } 245 _sumCount -= 1; 246 _findIndex = findIndex + 1; 247 }); 248 expect(_sumCount === 0).to.be.true; 249 250 _findIndex = 0; 251 _sumCount = expectWarnInfos.length; 252 warnInfos.forEach((err) => { 253 const message: string = parseLog(err.cause ?? err.message); 254 const findIndex: number = expectWarnInfos 255 .slice(_findIndex) 256 .findIndex((value) => value.message === message); 257 expect(findIndex !== -1).to.be.true; 258 _sumCount -= 1; 259 _findIndex = findIndex + 1; 260 }); 261 expect(_sumCount === 0).to.be.true; 262 263 done(); 264 }) 265 .catch(err => done(err)); 266 }); 267 }); 268});