• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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});