forked from harmony_car/subject-two
		
	feat: 运行
This commit is contained in:
		
							parent
							
								
									ed236df1d6
								
							
						
					
					
						commit
						be472470ff
					
				| @ -4,13 +4,13 @@ | ||||
|       { | ||||
|         "name": "default", | ||||
|         "material": { | ||||
|           "certpath": "C:\\Users\\surenjun\\.ohos\\config\\openharmony\\auto_ohos_default_end2_bak_com.oh.dts.cer", | ||||
|           "storePassword": "0000001BBCF008AF436022E84525958DDA30DAACBAE95FB89880984155936D5A2B2211EBFC642FCC2C063B", | ||||
|           "certpath": "/Users/wangzhongjie/.ohos/config/openharmony/auto_ohos_default_subject-two_com.oh.dts.cer", | ||||
|           "storePassword": "0000001A3E7D97C4BC5819BCBC0470AB1397AAD09AC6E70069CFC6FD7D21A58A50AA6EE3FEBCDA027D71", | ||||
|           "keyAlias": "debugKey", | ||||
|           "keyPassword": "0000001B43018ED537D1DAF50E0FBEDF8E721D4B33B58ED0429751E6224D301D25C6BB44B66F90B57FFDEF", | ||||
|           "profile": "C:\\Users\\surenjun\\.ohos\\config\\openharmony\\auto_ohos_default_end2_bak_com.oh.dts.p7b", | ||||
|           "keyPassword": "0000001A764ACBDC861BE169BE8B85E333F52659116CD5B8F12254C0F8F893E26884787B99199D49B10C", | ||||
|           "profile": "/Users/wangzhongjie/.ohos/config/openharmony/auto_ohos_default_subject-two_com.oh.dts.p7b", | ||||
|           "signAlg": "SHA256withECDSA", | ||||
|           "storeFile": "C:\\Users\\surenjun\\.ohos\\config\\openharmony\\auto_ohos_default_end2_bak_com.oh.dts.p12" | ||||
|           "storeFile": "/Users/wangzhongjie/.ohos/config/openharmony/auto_ohos_default_subject-two_com.oh.dts.p12" | ||||
|         } | ||||
|       } | ||||
|     ], | ||||
|  | ||||
							
								
								
									
										13
									
								
								entry/oh-package-lock.json5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								entry/oh-package-lock.json5
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| { | ||||
|   "lockfileVersion": 1, | ||||
|   "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", | ||||
|   "specifiers": { | ||||
|     "@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6" | ||||
|   }, | ||||
|   "packages": { | ||||
|     "@ohos/hypium@1.0.6": { | ||||
|       "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz", | ||||
|       "integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ==" | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										12
									
								
								entry/oh-package.json5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								entry/oh-package.json5
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| { | ||||
|   "license": "", | ||||
|   "devDependencies": { | ||||
|     "@ohos/hypium": "1.0.6" | ||||
|   }, | ||||
|   "author": "", | ||||
|   "name": "myapplication", | ||||
|   "description": "Please describe the basic information.", | ||||
|   "main": "", | ||||
|   "version": "1.0.0", | ||||
|   "dependencies": {} | ||||
| } | ||||
| @ -0,0 +1,45 @@ | ||||
| ## 1.0.6 | ||||
| 
 | ||||
| - 适配模块化编译 | ||||
| - 适配IDE覆盖率数据输出 | ||||
| 
 | ||||
| ## 1.0.5 | ||||
| 
 | ||||
| - 优化接口异常场景处理能力 | ||||
| - 修复大规模压力测试下内存溢出问题 | ||||
| - 修复测试脚本定义扩展原型方法与框架的兼容性问题 | ||||
| - 异步promise状态判断断言与取反断言兼容 | ||||
| 
 | ||||
| ## 1.0.4 | ||||
| 
 | ||||
| - 新增异步promise状态判断断言 | ||||
| - 新增基础数据判断断言 | ||||
| - 新增断言异常信息描述 | ||||
| - 优化用例计时逻辑,采用相对时间计时 | ||||
| - 修改用例执行过程,异步执行 | ||||
| - 修复用例结果偶现的乱序问题 | ||||
| 
 | ||||
| ## 1.0.3 | ||||
| 
 | ||||
| - 新增mock对象的能力,支持mock无参数函数 | ||||
| - 新增测试套、测试用例随机执行功能 | ||||
| - 解决测试套声明不规范,导致用例加载异常的问题 | ||||
| - 修复命令行窗口输出乱序的问题 | ||||
| 
 | ||||
| ## 1.0.2 | ||||
| 
 | ||||
| - 新增mock接口,判断当前mock方法状态、使用次数 | ||||
| - 修复用例耗时统计问题 | ||||
| - 修改断言功能,断言失败后,会抛出异常 | ||||
| 
 | ||||
| ## 1.0.1 | ||||
| - 新增mock基础能力 | ||||
| - 修复部分断言失败后,消息提示异常问题 | ||||
| 
 | ||||
| ## 1.0.0 | ||||
| - 新增应用日志关键字查询接口,查询hilog日志中是否包含指定字符串 | ||||
| - 支持用例筛选功能,用于指定测试用例的执行。可按用例名称、类型、规模、级别与测试套名称筛选 | ||||
| - 支持新SDK下单元测试 | ||||
| - 支持dry run 功能,通过命令行传参数,返回当前测试套用例名称全集 | ||||
| - 新增框架接口声明文件,用于deveco联想 | ||||
| - 修复用例状态统计问题 | ||||
| @ -0,0 +1,219 @@ | ||||
| <div style="text-align: center;font-size: xxx-large" >Hypium</div> | ||||
| <div style="text-align: center">A unit test framework for OpenHarmonyOS application</div> | ||||
| 
 | ||||
| ## Hypium是什么? | ||||
| *** | ||||
| - Hypium是OpenHarmony上的测试框架,提供测试用例编写、执行、结果显示能力,用于OpenHarmony系统应用接口以及应用界面测试。 | ||||
| - Hypium结构化模型:hypium工程主要由List.test.js与TestCase.test.js组成。 | ||||
| ``` | ||||
| rootProject                  // Hypium工程根目录 | ||||
| ├── moduleA | ||||
| │   ├── src | ||||
| │      ├── main                   // 被测试应用目录 | ||||
| │      ├── ohosTest               // 测试用例目录 | ||||
| │         ├── js/ets | ||||
| │            └── test | ||||
| │               └── List.test.js      // 测试用例加载脚本,ets目录下为.ets后缀 | ||||
| │               └── TestCase.test.js  // 测试用例脚本,ets目录下为.ets后缀 | ||||
| └── moduleB | ||||
|     ... | ||||
| │               └── List.test.js      // 测试用例加载脚本,ets目录下为.ets后缀 | ||||
| │               └── TestCase.test.js  // 测试用例脚本,ets目录下为.ets后缀 | ||||
| ``` | ||||
| 
 | ||||
| ## 安装使用 | ||||
| *** | ||||
| - 在DevEco Studio内使用Hypium | ||||
| - 工程级package.json内配置: | ||||
| ```json | ||||
| "dependencies": { | ||||
|     "@ohos/hypium": "1.0.6" | ||||
| } | ||||
| ``` | ||||
| 注: | ||||
| hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导: | ||||
| [Deveco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio) | ||||
| 
 | ||||
| #### 通用语法 | ||||
| 
 | ||||
| - 测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。 | ||||
| 
 | ||||
| | No. | API        | 功能说明                                                                                                               | | ||||
| | --- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | | ||||
| | 1   | describe   | 定义一个测试套,支持两个参数:测试套名称和测试套函数                                                                   | | ||||
| | 2   | beforeAll  | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数                           | | ||||
| | 3   | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 | | ||||
| | 4   | afterEach  | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 | | ||||
| | 5   | afterAll   | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数                           | | ||||
| | 6   | it         | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数                                                           | | ||||
| | 7   | expect     | 支持bool类型判断等多种断言方法                                                                                         | | ||||
| 
 | ||||
| #### 断言库 | ||||
| 
 | ||||
| - 示例代码: | ||||
| 
 | ||||
| ```javascript | ||||
|   expect(${actualvalue}).assertX(${expectvalue}) | ||||
| ``` | ||||
| 
 | ||||
| - 断言功能列表: | ||||
| 
 | ||||
| | No.  | API                              | 功能说明                                                                                       | | ||||
| | :--- | :------------------------------- | ---------------------------------------------------------------------------------------------- | | ||||
| | 1    | assertClose                      | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1)                                  | | ||||
| | 2    | assertContain                    | 检验actualvalue中是否包含expectvalue                                                           | | ||||
| | 3    | assertDeepEquals                 | @since1.0.4 检验actualvalue和expectvalue(0)是否是同一个对象                                    | | ||||
| | 4    | assertEqual                      | 检验actualvalue是否等于expectvalue[0]                                                          | | ||||
| | 5    | assertFail                       | 抛出一个错误                                                                                   | | ||||
| | 6    | assertFalse                      | 检验actualvalue是否是false                                                                     | | ||||
| | 7    | assertTrue                       | 检验actualvalue是否是true                                                                      | | ||||
| | 8    | assertInstanceOf                 | 检验actualvalue是否是expectvalue类型                                                           | | ||||
| | 9    | assertLarger                     | 检验actualvalue是否大于expectvalue                                                             | | ||||
| | 10   | assertLess                       | 检验actualvalue是否小于expectvalue                                                             | | ||||
| | 11   | assertNaN                        | @since1.0.4 检验actualvalue是否是NaN                                                           | | ||||
| | 12   | assertNegUnlimited               | @since1.0.4 检验actualvalue是否等于Number.NEGATIVE_INFINITY                                    | | ||||
| | 13   | assertNull                       | 检验actualvalue是否是null                                                                      | | ||||
| | 14   | assertPosUnlimited               | @since1.0.4 检验actualvalue是否等于Number.POSITIVE_INFINITY                                    | | ||||
| | 15   | assertPromiseIsPending           | @since1.0.4 检验actualvalue是否处于Pending状态【actualvalue为promse对象】                      | | ||||
| | 16   | assertPromiseIsRejected          | @since1.0.4 检验actualvalue是否处于Rejected状态【同15】                                        | | ||||
| | 17   | assertPromiseIsRejectedWith      | @since1.0.4 检验actualvalue是否处于Rejected状态,并且比较执行的结果值【同15】                  | | ||||
| | 18   | assertPromiseIsRejectedWithError | @since1.0.4 检验actualvalue是否处于Rejected状态并有异常,同时比较异常的类型和message值【同15】 | | ||||
| | 19   | assertPromiseIsResolved          | @since1.0.4 检验actualvalue是否处于Resolved状态【同15】                                        | | ||||
| | 20   | assertPromiseIsResolvedWith      | @since1.0.4 检验actualvalue是否处于Resolved状态,并且比较执行的结果值【同15】                  | | ||||
| | 21   | assertThrowError                 | 检验actualvalue抛出Error内容是否是expectValue                                                  | | ||||
| | 22   | assertUndefined                  | 检验actualvalue是否是undefined                                                                 | | ||||
| | 23   | not                              | @since1.0.4 断言结果取反                                                                       | | ||||
| 
 | ||||
| 
 | ||||
|   示例代码: | ||||
| 
 | ||||
| ```javascript | ||||
|   import { describe, it, expect } from '@ohos/hypium'; | ||||
| 
 | ||||
|   export default async function assertCloseTest() { | ||||
|     describe('assertClose', function () { | ||||
|       it('assertClose_success', 0, function () { | ||||
|         let a = 100; | ||||
|         let b = 0.1; | ||||
|         expect(a).assertClose(99, b); | ||||
|       }) | ||||
|     }) | ||||
|   } | ||||
| ``` | ||||
| 
 | ||||
| #### 公共系统能力 | ||||
| 
 | ||||
| | No.  | API                                                     | 功能描述                                                     | | ||||
| | ---- | ------------------------------------------------------- | ------------------------------------------------------------ | | ||||
| | 1    | existKeyword(keyword: string, timeout: number): boolean | @since1.0.3 hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 | | ||||
| | 2    | actionStart(tag: string): void                          | @since1.0.3 cmd窗口输出开始tag                               | | ||||
| | 3    | actionEnd(tag: string): void                            | @since1.0.3 cmd窗口输出结束tag                               | | ||||
| 
 | ||||
|   示例代码: | ||||
| 
 | ||||
| ```javascript | ||||
| import { describe, it, expect, SysTestKit} from '@ohos/hypium'; | ||||
| 
 | ||||
| export default function existKeywordTest() { | ||||
|     describe('existKeywordTest', function () { | ||||
|         it('existKeyword',DEFAULT, async function () { | ||||
|             console.info("HelloTest"); | ||||
|             let isExist = await SysTestKit.existKeyword('HelloTest'); | ||||
|             console.info('isExist ------>' + isExist); | ||||
|         }) | ||||
|     }) | ||||
| } | ||||
| ``` | ||||
| ```javascript | ||||
| import { describe, it, expect, SysTestKit} from '@ohos/hypium'; | ||||
| 
 | ||||
| export default function actionTest() { | ||||
|     describe('actionTest', function () { | ||||
|         it('existKeyword',DEFAULT, async function () { | ||||
|             let tag = '[MyTest]'; | ||||
| 			SysTestKit.actionStart(tag); | ||||
|             //do something | ||||
|             SysTestKit.actionEnd(tag); | ||||
|         }) | ||||
|     }) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| #### 专项能力 | ||||
| 
 | ||||
| - 测试用例属性筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是先在测试用例上标记用例属性后,再在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。 | ||||
| 
 | ||||
| | Key      | 含义说明     | Value取值范围                                                                                                                                          | | ||||
| | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||||
| | level    | 用例级别     | "0","1","2","3","4", 例如:-s level 1                                                                                                                  | | ||||
| | size     | 用例粒度     | "small","medium","large", 例如:-s size small                                                                                                          | | ||||
| | testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience", 例如:-s testType function | | ||||
| 
 | ||||
|   示例代码 | ||||
| 
 | ||||
| ```javascript | ||||
| import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium'; | ||||
| 
 | ||||
| export default function attributeTest() { | ||||
|     describe('attributeTest', function () { | ||||
|         it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () { | ||||
|             console.info('Hello Test'); | ||||
|         }) | ||||
|     }) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
|   示例命令 | ||||
| ```shell   | ||||
| XX -s level 1 -s size small -s testType function | ||||
| ``` | ||||
| 该命令的作用是:筛选测试应用中同时满足a)用例级别是1 b)用例粒度是small c)用例测试类型是function 三个条件的用例执行。 | ||||
| 
 | ||||
| - 测试套/测试用例名称筛选能力(测试套与用例名称用“#”号连接,多个用“,”英文逗号分隔) | ||||
| 
 | ||||
| | Key      | 含义说明                | Value取值范围                                                                                | | ||||
| | -------- | ----------------------- | -------------------------------------------------------------------------------------------- | | ||||
| | class    | 指定要执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s class attributeTest#testAttributeIt    | | ||||
| | notClass | 指定不执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s notClass attributeTest#testAttributeIt | | ||||
| 
 | ||||
|   示例命令 | ||||
| ```shell   | ||||
| XX -s class attributeTest#testAttributeIt,abilityTest#testAbilityIt | ||||
| ``` | ||||
| 该命令的作用是:筛选测试应用中attributeTest测试套下的testAttributeIt测试用例,abilityTest测试套下的testAbilityIt测试用例,只执行这两条用例。 | ||||
| 
 | ||||
| - 其他能力 | ||||
| 
 | ||||
| | 能力项       | Key     | 含义说明                     | Value取值范围                                  | | ||||
| | ------------ | ------- | ---------------------------- | ---------------------------------------------- | | ||||
| | 随机执行能力 | random  | 测试套&测试用例随机执行      | true, 不传参默认为false, 例如:-s random true | | ||||
| | 空跑能力     | dryRun  | 显示要执行的测试用例信息全集 | true , 不传参默认为false,例如:-s dryRun true | | ||||
| | 异步超时能力 | timeout | 异步用例执行的超时时间       | 正整数 , 单位ms,例如:-s timeout 5000         | | ||||
| 
 | ||||
| ##### 约束限制 | ||||
| 随机执行能力和空跑能力从npm包1.0.3版本开始支持 | ||||
| 
 | ||||
| #### Mock能力 | ||||
| 
 | ||||
| ##### 约束限制 | ||||
| 
 | ||||
| 单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium/v/1.0.1)开始支持 | ||||
| 
 | ||||
| ## 约束 | ||||
| 
 | ||||
| *** | ||||
|     本模块首批接口从OpenHarmony SDK API version 8开始支持。 | ||||
| 
 | ||||
| ## Hypium开放能力隐私声明 | ||||
| 
 | ||||
| -  我们如何收集和使用您的个人信息 | ||||
| 	您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。 | ||||
| -  SDK处理的个人信息 | ||||
| 	不涉及。 | ||||
| -  SDK集成第三方服务声明 | ||||
| 	不涉及。 | ||||
| -  SDK数据安全保护 | ||||
| 	不涉及。 | ||||
| -  SDK版本更新声明 | ||||
| 	为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。 | ||||
| 
 | ||||
							
								
								
									
										136
									
								
								entry/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								entry/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,136 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License") | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| export const DEFAULT = 0B0000 | ||||
| 
 | ||||
| export const when: when; | ||||
| 
 | ||||
| export enum TestType { | ||||
|     FUNCTION = 0B1, | ||||
|     PERFORMANCE = 0B1 << 1, | ||||
|     POWER = 0B1 << 2, | ||||
|     RELIABILITY = 0B1 << 3, | ||||
|     SECURITY = 0B1 << 4, | ||||
|     GLOBAL = 0B1 << 5, | ||||
|     COMPATIBILITY = 0B1 << 6, | ||||
|     USER = 0B1 << 7, | ||||
|     STANDARD = 0B1 << 8, | ||||
|     SAFETY = 0B1 << 9, | ||||
|     RESILIENCE = 0B1 << 10 | ||||
| } | ||||
| 
 | ||||
| export enum Size { | ||||
|     SMALLTEST = 0B1 << 16, | ||||
|     MEDIUMTEST = 0B1 << 17, | ||||
|     LARGETEST = 0B1 << 18 | ||||
| } | ||||
| 
 | ||||
| export enum Level { | ||||
|     LEVEL0 = 0B1 << 24, | ||||
|     LEVEL1 = 0B1 << 25, | ||||
|     LEVEL2 = 0B1 << 26, | ||||
|     LEVEL3 = 0B1 << 27, | ||||
|     LEVEL4 = 0B1 << 28 | ||||
| } | ||||
| 
 | ||||
| export function describe(testSuiteName: string, callback: Function): void | ||||
| 
 | ||||
| export function beforeEach(callback: Function): void | ||||
| 
 | ||||
| export function afterEach(callback: Function): void | ||||
| 
 | ||||
| export function beforeAll(callback: Function): void | ||||
| 
 | ||||
| export function afterAll(callback: Function): void | ||||
| 
 | ||||
| export function it(testCaseName: string, attribute: (TestType | Size | Level), callback: Function) | ||||
| 
 | ||||
| export interface Assert { | ||||
|     assertClose(expectValue: number, precision: number): void | ||||
|     assertContain(expectValue: any): void | ||||
|     assertEqual(expectValue: any): void | ||||
|     assertFail(): void | ||||
|     assertFalse(): void | ||||
|     assertTrue(): void | ||||
|     assertInstanceOf(expectValue: string): void | ||||
|     assertLarger(expectValue: number): void | ||||
|     assertLess(expectValue: number): void | ||||
|     assertNull(): void | ||||
|     assertThrowError(expectValue: string): void | ||||
|     assertUndefined(): void | ||||
|     assertLargerOrEqual(expectValue: number):void | ||||
|     assertLessOrEqual(expectValue: number):void | ||||
|     assertNaN():void | ||||
|     assertNegUnlimited(): void | ||||
|     assertPosUnlimited(): void | ||||
|     not(): Assert; | ||||
|     assertDeepEquals(expectValue: any):void | ||||
|     assertPromiseIsPending(): void | ||||
|     assertPromiseIsRejected(): void | ||||
|     assertPromiseIsRejectedWith(expectValue?: any): void | ||||
|     assertPromiseIsRejectedWithError(...expectValue): void | ||||
|     assertPromiseIsResolved(): void | ||||
|     assertPromiseIsResolvedWith(expectValue?: any): void | ||||
| } | ||||
| 
 | ||||
| export function expect(actualValue?: any): Assert | ||||
| 
 | ||||
| export class ArgumentMatchers { | ||||
|     static any; | ||||
|     static anyString; | ||||
|     static anyBoolean; | ||||
|     static anyNumber; | ||||
|     static anyObj; | ||||
|     static anyFunction; | ||||
|     static matchRegexs(Regex: RegExp): void | ||||
| } | ||||
| 
 | ||||
| declare interface when { | ||||
|     afterReturn(value: any): any | ||||
|     afterReturnNothing(): undefined | ||||
|     afterAction(action: any): any | ||||
|     afterThrow(e_msg: string): string | ||||
|     (argMatchers?: any): when; | ||||
| } | ||||
| 
 | ||||
| export interface VerificationMode { | ||||
|     times(count: Number): void | ||||
|     never(): void | ||||
|     once(): void | ||||
|     atLeast(count: Number): void | ||||
|     atMost(count: Number): void | ||||
| } | ||||
| 
 | ||||
| export class MockKit { | ||||
|     constructor() | ||||
|     mockFunc(obj: Object, func: Function): Function | ||||
|     mockObject(obj: Object): Object | ||||
|     verify(methodName: String, argsArray: Array<any>): VerificationMode | ||||
|     ignoreMock(obj: Object, func: Function): void | ||||
|     clear(obj: Object): void | ||||
|     clearAll(): void | ||||
| } | ||||
| 
 | ||||
| export class SysTestKit { | ||||
|     static actionStart(tag: string): void | ||||
|     static actionEnd(tag: string): void | ||||
|     static existKeyword(keyword: string, timeout?: number): boolean | ||||
| } | ||||
| 
 | ||||
| export class Hypium { | ||||
|     static setData(data: {[key: string]: any}): void | ||||
|     static setTimeConfig(systemTime: any) | ||||
|     static hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void | ||||
| } | ||||
| @ -0,0 +1,92 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License") | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import Core from './src/main/core'; | ||||
| import {DEFAULT, TestType, Size, Level} from './src/main/Constant'; | ||||
| import DataDriver from './src/main/module/config/DataDriver'; | ||||
| import ExpectExtend from './src/main/module/assert/ExpectExtend'; | ||||
| import OhReport from './src/main/module/report/OhReport'; | ||||
| import SysTestKit from './src/main/module/kit/SysTestKit'; | ||||
| import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; | ||||
| import {MockKit, when} from './src/main/module/mock/MockKit'; | ||||
| import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; | ||||
| 
 | ||||
| class Hypium { | ||||
|     static setData(data) { | ||||
|         const core = Core.getInstance(); | ||||
|         const dataDriver = new DataDriver({data}); | ||||
|         core.addService('dataDriver', dataDriver); | ||||
|     } | ||||
| 
 | ||||
|     static setTimeConfig(systemTime) { | ||||
|         SysTestKit.systemTime = systemTime; | ||||
|     } | ||||
| 
 | ||||
|     static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { | ||||
|         const core = Core.getInstance(); | ||||
|         const expectExtend = new ExpectExtend({ | ||||
|             'id': 'extend' | ||||
|         }); | ||||
|         core.addService('expect', expectExtend); | ||||
|         const ohReport = new OhReport({ | ||||
|             'delegator': abilityDelegator, | ||||
|             'abilityDelegatorArguments': abilityDelegatorArguments | ||||
|         }); | ||||
|         SysTestKit.delegator = abilityDelegator; | ||||
|         core.addService('report', ohReport); | ||||
|         core.init(); | ||||
|         core.subscribeEvent('spec', ohReport); | ||||
|         core.subscribeEvent('suite', ohReport); | ||||
|         core.subscribeEvent('task', ohReport); | ||||
|         const configService = core.getDefaultService('config'); | ||||
| 
 | ||||
|         let testParameters = {}; | ||||
|         if (abilityDelegatorArguments !== null) { | ||||
|             testParameters = configService.translateParams(abilityDelegatorArguments.parameters); | ||||
|         } | ||||
|         console.info('parameters:' + JSON.stringify(testParameters)); | ||||
|         configService.setConfig(testParameters); | ||||
| 
 | ||||
|         testsuite(); | ||||
|         if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) { | ||||
|             globalThis.setupUiTestEnvironment().then(() => { | ||||
|                 console.info('UiTestKit::after run uitest setup, start run testcases'); | ||||
|                 core.execute(abilityDelegator); | ||||
|             }).catch((error) => { | ||||
|                 console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error); | ||||
|                 core.execute(abilityDelegator); | ||||
|             }); | ||||
|         } else { | ||||
|             console.info('UiTestKit:: no need to setup uitest, start run testcases'); | ||||
|             core.execute(abilityDelegator); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { | ||||
|     Hypium, | ||||
|     Core, | ||||
|     DEFAULT, | ||||
|     TestType, | ||||
|     Size, | ||||
|     Level, | ||||
|     DataDriver, | ||||
|     ExpectExtend, | ||||
|     OhReport, | ||||
|     SysTestKit, | ||||
|     describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, | ||||
|     MockKit, when, | ||||
|     ArgumentMatchers | ||||
| }; | ||||
| @ -0,0 +1,92 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License") | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import Core from './src/main/core'; | ||||
| import {DEFAULT, TestType, Size, Level} from './src/main/Constant'; | ||||
| import DataDriver from './src/main/module/config/DataDriver'; | ||||
| import ExpectExtend from './src/main/module/assert/ExpectExtend'; | ||||
| import OhReport from './src/main/module/report/OhReport'; | ||||
| import SysTestKit from './src/main/module/kit/SysTestKit'; | ||||
| import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; | ||||
| import {MockKit, when} from './src/main/module/mock/MockKit'; | ||||
| import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; | ||||
| 
 | ||||
| class Hypium { | ||||
|     static setData(data) { | ||||
|         const core = Core.getInstance(); | ||||
|         const dataDriver = new DataDriver({data}); | ||||
|         core.addService('dataDriver', dataDriver); | ||||
|     } | ||||
| 
 | ||||
|     static setTimeConfig(systemTime) { | ||||
|         SysTestKit.systemTime = systemTime; | ||||
|     } | ||||
| 
 | ||||
|     static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { | ||||
|         const core = Core.getInstance(); | ||||
|         const expectExtend = new ExpectExtend({ | ||||
|             'id': 'extend' | ||||
|         }); | ||||
|         core.addService('expect', expectExtend); | ||||
|         const ohReport = new OhReport({ | ||||
|             'delegator': abilityDelegator, | ||||
|             'abilityDelegatorArguments': abilityDelegatorArguments | ||||
|         }); | ||||
|         SysTestKit.delegator = abilityDelegator; | ||||
|         core.addService('report', ohReport); | ||||
|         core.init(); | ||||
|         core.subscribeEvent('spec', ohReport); | ||||
|         core.subscribeEvent('suite', ohReport); | ||||
|         core.subscribeEvent('task', ohReport); | ||||
|         const configService = core.getDefaultService('config'); | ||||
| 
 | ||||
|         let testParameters = {}; | ||||
|         if (abilityDelegatorArguments !== null) { | ||||
|             testParameters = configService.translateParams(abilityDelegatorArguments.parameters); | ||||
|         } | ||||
|         console.info('parameters:' + JSON.stringify(testParameters)); | ||||
|         configService.setConfig(testParameters); | ||||
| 
 | ||||
|         testsuite(); | ||||
|         if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) { | ||||
|             globalThis.setupUiTestEnvironment().then(() => { | ||||
|                 console.info('UiTestKit::after run uitest setup, start run testcases'); | ||||
|                 core.execute(abilityDelegator); | ||||
|             }).catch((error) => { | ||||
|                 console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error); | ||||
|                 core.execute(abilityDelegator); | ||||
|             }); | ||||
|         } else { | ||||
|             console.info('UiTestKit:: no need to setup uitest, start run testcases'); | ||||
|             core.execute(abilityDelegator); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { | ||||
|     Hypium, | ||||
|     Core, | ||||
|     DEFAULT, | ||||
|     TestType, | ||||
|     Size, | ||||
|     Level, | ||||
|     DataDriver, | ||||
|     ExpectExtend, | ||||
|     OhReport, | ||||
|     SysTestKit, | ||||
|     describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, | ||||
|     MockKit, when, | ||||
|     ArgumentMatchers | ||||
| }; | ||||
| @ -0,0 +1,11 @@ | ||||
| { | ||||
|   "name": "@ohos/hypium", | ||||
|   "version": "1.0.6", | ||||
|   "description": "A unit test framework for OpenHarmony application", | ||||
|   "main": "index.js", | ||||
|   "keywords": [], | ||||
|   "author": "huawei", | ||||
|   "license": "Apache-2.0", | ||||
|   "dependencies": { | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,47 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * define the testcase type : TestType, Size , Level | ||||
|  */ | ||||
| export const DEFAULT = 0B0000; | ||||
| 
 | ||||
| export class TestType { | ||||
|     static FUNCTION = 0B1; | ||||
|     static PERFORMANCE = 0B1 << 1; | ||||
|     static POWER = 0B1 << 2; | ||||
|     static RELIABILITY = 0B1 << 3; | ||||
|     static SECURITY = 0B1 << 4; | ||||
|     static GLOBAL = 0B1 << 5; | ||||
|     static COMPATIBILITY = 0B1 << 6; | ||||
|     static USER = 0B1 << 7; | ||||
|     static STANDARD = 0B1 << 8; | ||||
|     static SAFETY = 0B1 << 9; | ||||
|     static RESILIENCE = 0B1 << 10; | ||||
| } | ||||
| 
 | ||||
| export class Size { | ||||
|     static SMALLTEST = 0B1 << 16; | ||||
|     static MEDIUMTEST = 0B1 << 17; | ||||
|     static LARGETEST = 0B1 << 18; | ||||
| } | ||||
| 
 | ||||
| export class Level { | ||||
|     static LEVEL0 = 0B1 << 24; | ||||
|     static LEVEL1 = 0B1 << 25; | ||||
|     static LEVEL2 = 0B1 << 26; | ||||
|     static LEVEL3 = 0B1 << 27; | ||||
|     static LEVEL4 = 0B1 << 28; | ||||
| } | ||||
| @ -0,0 +1,159 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import {SuiteService, SpecService, ExpectService, ReportService} from './service'; | ||||
| import {ConfigService} from './module/config/configService'; | ||||
| import {SpecEvent, TaskEvent, SuiteEvent} from './event'; | ||||
| 
 | ||||
| /** | ||||
|  * core service for execute testcase. | ||||
|  */ | ||||
| class Core { | ||||
|     static getInstance() { | ||||
|         if (!this.instance) { | ||||
|             this.instance = new Core(); | ||||
|         } | ||||
|         return this.instance; | ||||
|     } | ||||
| 
 | ||||
|     constructor() { | ||||
|         this.instance = null; | ||||
|         this.services = { | ||||
|             suite: {}, | ||||
|             spec: {}, | ||||
|             config: {}, | ||||
|             expect: {}, | ||||
|             log: {}, | ||||
|             report: {} | ||||
| 
 | ||||
|         }; | ||||
|         this.events = { | ||||
|             suite: {}, | ||||
|             spec: {}, | ||||
|             task: {} | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     addService(name, service) { | ||||
|         let serviceObj = {}; | ||||
|         if (!this.services[name]) { | ||||
|             this.services[name] = serviceObj; | ||||
|         } else { | ||||
|             serviceObj = this.services[name]; | ||||
|         } | ||||
|         serviceObj[service.id] = service; | ||||
|     } | ||||
| 
 | ||||
|     getDefaultService(name) { | ||||
|         return this.services[name].default; | ||||
|     } | ||||
| 
 | ||||
|     getServices(name) { | ||||
|         return this.services[name]; | ||||
|     } | ||||
| 
 | ||||
|     registerEvent(serviceName, event) { | ||||
|         let eventObj = {}; | ||||
|         if (!this.events[serviceName]) { | ||||
|             this.events[serviceName] = eventObj; | ||||
|         } else { | ||||
|             eventObj = this.events[serviceName]; | ||||
|         } | ||||
|         eventObj[event.id] = event; | ||||
|     } | ||||
| 
 | ||||
|     unRegisterEvent(serviceName, eventID) { | ||||
|         const eventObj = this.events[serviceName]; | ||||
|         if (eventObj) { | ||||
|             delete eventObj[eventID]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     subscribeEvent(serviceName, serviceObj) { | ||||
|         const eventObj = this.events[serviceName]; | ||||
|         if (eventObj) { | ||||
|             for (const attr in eventObj) { | ||||
|                 eventObj[attr]['subscribeEvent'](serviceObj); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fireEvents(serviceName, eventName) { | ||||
|         const eventObj = this.events[serviceName]; | ||||
|         if (!eventObj) { | ||||
|             return; | ||||
|         } | ||||
|         for (const attr in eventObj) { | ||||
|             await eventObj[attr][eventName](); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     addToGlobal(apis) { | ||||
|         if (typeof globalThis !== 'undefined') { | ||||
|             for (let api in apis) { | ||||
|                 globalThis[api] = apis[api]; | ||||
|             } | ||||
|         } | ||||
|         for (const api in apis) { | ||||
|             this[api] = apis[api]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     init() { | ||||
|         this.addService('suite', new SuiteService({id: 'default'})); | ||||
|         this.addService('spec', new SpecService({id: 'default'})); | ||||
|         this.addService('expect', new ExpectService({id: 'default'})); | ||||
|         this.addService('report', new ReportService({id: 'default'})); | ||||
|         this.addService('config', new ConfigService({id: 'default'})); | ||||
|         this.registerEvent('task', new TaskEvent({id: 'default', coreContext: this})); | ||||
|         this.registerEvent('suite', new SuiteEvent({id: 'default', coreContext: this})); | ||||
|         this.registerEvent('spec', new SpecEvent({id: 'default', coreContext: this})); | ||||
|         this.subscribeEvent('spec', this.getDefaultService('report')); | ||||
|         this.subscribeEvent('suite', this.getDefaultService('report')); | ||||
|         this.subscribeEvent('task', this.getDefaultService('report')); | ||||
|         const context = this; | ||||
|         for (const key in this.services) { | ||||
|             const serviceObj = this.services[key]; | ||||
|             for (const serviceID in serviceObj) { | ||||
|                 const service = serviceObj[serviceID]; | ||||
|                 service.init(context); | ||||
| 
 | ||||
|                 if (typeof service.apis !== 'function') { | ||||
|                     continue; | ||||
|                 } | ||||
|                 const apis = service.apis(); | ||||
|                 if (apis) { | ||||
|                     this.addToGlobal(apis); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     execute(abilityDelegator) { | ||||
|         const suiteService = this.getDefaultService('suite'); | ||||
|         const configService = this.getDefaultService('config'); | ||||
|         if (configService['dryRun'] === 'true') { | ||||
|             (async function () { | ||||
|                 await suiteService.dryRun(abilityDelegator); | ||||
|             })(); | ||||
|             return; | ||||
|         } | ||||
|         setTimeout(() => { | ||||
|             suiteService.execute(); | ||||
|         }, 10); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default Core; | ||||
| @ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class SpecEvent { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.coreContext = attr.context; | ||||
|         this.eventMonitors = []; | ||||
|     } | ||||
| 
 | ||||
|     subscribeEvent(service) { | ||||
|         this.eventMonitors.push(service); | ||||
|     } | ||||
| 
 | ||||
|     async specStart() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             await monitor['specStart'](); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async specDone() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             await monitor['specDone'](); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| class SuiteEvent { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.suiteContext = attr.coreContext; | ||||
|         this.eventMonitors = []; | ||||
|     } | ||||
| 
 | ||||
|     subscribeEvent(service) { | ||||
|         this.eventMonitors.push(service); | ||||
|     } | ||||
| 
 | ||||
|     async suiteStart() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             await monitor['suiteStart'](); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async suiteDone() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             await monitor['suiteDone'](); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| class TaskEvent { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.coreContext = attr.coreContext; | ||||
|         this.eventMonitors = []; | ||||
|     } | ||||
| 
 | ||||
|     subscribeEvent(service) { | ||||
|         this.eventMonitors.push(service); | ||||
|     } | ||||
| 
 | ||||
|     async taskStart() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             await monitor['taskStart'](); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async taskDone() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             await monitor['taskDone'](); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     incorrectFormat() { | ||||
|         for (const monitor of this.eventMonitors) { | ||||
|             monitor['incorrectFormat'](); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export {SpecEvent, TaskEvent, SuiteEvent}; | ||||
| @ -0,0 +1,44 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import Core from './core'; | ||||
| 
 | ||||
| const core = Core.getInstance(); | ||||
| 
 | ||||
| const describe = function (desc, func) { | ||||
|     return Reflect.has(core, 'describe') ? core.describe(desc, func) : (desc, func) => { }; | ||||
| }; | ||||
| const it = function (desc, filter, func) { | ||||
|     return Reflect.has(core, 'it') ? core.it(desc, filter, func) : (desc, filter, func) => { }; | ||||
| }; | ||||
| const beforeEach = function (func) { | ||||
|     return Reflect.has(core, 'beforeEach') ? core.beforeEach(func) : (func) => { }; | ||||
| }; | ||||
| const afterEach = function (func) { | ||||
|     return Reflect.has(core, 'afterEach') ? core.afterEach(func) : (func) => { }; | ||||
| }; | ||||
| const beforeAll = function (func) { | ||||
|     return Reflect.has(core, 'beforeAll') ? core.beforeAll(func) : (func) => { }; | ||||
| }; | ||||
| const afterAll = function (func) { | ||||
|     return Reflect.has(core, 'afterAll') ? core.afterAll(func) : (func) => { }; | ||||
| }; | ||||
| const expect = function (actualValue) { | ||||
|     return Reflect.has(core, 'expect') ? core.expect(actualValue) : (actualValue) => { }; | ||||
| }; | ||||
| 
 | ||||
| export { | ||||
|     describe, it, beforeAll, beforeEach, afterEach, afterAll, expect | ||||
| }; | ||||
| @ -0,0 +1,85 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import assertNull from './assertNull'; | ||||
| import assertClose from './assertClose'; | ||||
| import assertContain from './assertContain'; | ||||
| import assertLess from './assertLess'; | ||||
| import assertLarger from './assertLarger'; | ||||
| import assertFail from './assertFail'; | ||||
| import assertUndefined from './assertUndefined'; | ||||
| import assertFalse from './assertFalse'; | ||||
| import assertInstanceOf from './assertInstanceOf'; | ||||
| import assertThrowError from './assertThrowError'; | ||||
| import assertLargerOrEqual from './assertLargerOrEqual' | ||||
| import assertLessOrEqual from './assertLessOrEqual' | ||||
| import assertNaN from './assertNaN' | ||||
| import assertNegUnlimited from './assertNegUnlimited' | ||||
| import assertPosUnlimited from './assertPosUnlimited' | ||||
| import assertDeepEquals from './deepEquals/assertDeepEquals' | ||||
| import assertPromiseIsPending from './assertPromiseIsPending'; | ||||
| import assertPromiseIsRejected from './assertPromiseIsRejected'; | ||||
| import assertPromiseIsRejectedWith from './assertPromiseIsRejectedWith'; | ||||
| import assertPromiseIsRejectedWithError from './assertPromiseIsRejectedWithError'; | ||||
| import assertPromiseIsResolved from './assertPromiseIsResolved'; | ||||
| import assertPromiseIsResolvedWith from './assertPromiseIsResolvedWith'; | ||||
| class ExpectExtend { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.matchers = {}; | ||||
|     } | ||||
| 
 | ||||
|     extendsMatchers() { | ||||
|         this.matchers.assertNull = assertNull; | ||||
|         this.matchers.assertClose = assertClose; | ||||
|         this.matchers.assertContain = assertContain; | ||||
|         this.matchers.assertLess = assertLess; | ||||
|         this.matchers.assertLarger = assertLarger; | ||||
|         this.matchers.assertFail = assertFail; | ||||
|         this.matchers.assertUndefined = assertUndefined; | ||||
|         this.matchers.assertFalse = assertFalse; | ||||
|         this.matchers.assertInstanceOf = assertInstanceOf; | ||||
|         this.matchers.assertThrowError = assertThrowError; | ||||
|         this.matchers.assertLargerOrEqual = assertLargerOrEqual; | ||||
|         this.matchers.assertLessOrEqual = assertLessOrEqual; | ||||
|         this.matchers.assertNaN = assertNaN; | ||||
|         this.matchers.assertNegUnlimited = assertNegUnlimited; | ||||
|         this.matchers.assertPosUnlimited = assertPosUnlimited; | ||||
|         this.matchers.assertDeepEquals = assertDeepEquals; | ||||
|         this.matchers.assertPromiseIsPending = assertPromiseIsPending; | ||||
|         this.matchers.assertPromiseIsRejected = assertPromiseIsRejected; | ||||
|         this.matchers.assertPromiseIsRejectedWith = assertPromiseIsRejectedWith; | ||||
|         this.matchers.assertPromiseIsRejectedWithError = assertPromiseIsRejectedWithError; | ||||
|         this.matchers.assertPromiseIsResolved = assertPromiseIsResolved; | ||||
|         this.matchers.assertPromiseIsResolvedWith = assertPromiseIsResolvedWith; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|         this.extendsMatchers(); | ||||
|         const expectService = this.coreContext.getDefaultService('expect'); | ||||
|         expectService.addMatchers(this.matchers); | ||||
|     } | ||||
| 
 | ||||
|     apis() { | ||||
|         return { | ||||
|             'expect': function (actualValue) { | ||||
|                 return this.coreContext.getDefaultService('expect').expect(actualValue); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default ExpectExtend; | ||||
| @ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertClose(actualValue, expected) { | ||||
|     console.log('expected:' + expected[0] + ',precision:' + expected[1]); | ||||
|     if (actualValue === null && expected[0] === null) { | ||||
|         throw new Error('actualValue and expected can not be both null!!!'); | ||||
|     } | ||||
|     let result; | ||||
|     let diff = Math.abs(expected[0] - actualValue); | ||||
|     let actualAbs = Math.abs(actualValue); | ||||
|     if ((actualAbs - 0) === 0) { | ||||
|         if ((diff - 0) === 0) { | ||||
|             result = true; | ||||
|         } else { | ||||
|             result = false; | ||||
|         } | ||||
|     } else if (diff / actualAbs < expected[1]) { | ||||
|         result = true; | ||||
|     } else { | ||||
|         result = false; | ||||
|     } | ||||
|     return { | ||||
|         pass: result, | ||||
|         message: '|' + actualValue + ' - ' + expected[0] + '|/' + actualValue + ' is not less than ' + expected[1] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertClose; | ||||
| @ -0,0 +1,35 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertContain(actualValue, expect) { | ||||
|     let result = false; | ||||
|     if (Object.prototype.toString.call(actualValue).indexOf('Array')) { | ||||
|         for (let i in actualValue) { | ||||
|             if (actualValue[i] == expect[0]) { | ||||
|                 result = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     let type = Object.prototype.toString.call(actualValue); | ||||
|     if (type === '[object String]') { | ||||
|         result = actualValue.indexOf(expect[0]) >= 0; | ||||
|     } | ||||
|     return { | ||||
|         pass: result, | ||||
|         message: 'expect false, ' + actualValue + ' do not have  ' + expect[0] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertContain; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertFail() { | ||||
|     return { | ||||
|         pass: false, | ||||
|         message: 'fail ' | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertFail; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertFalse(actualValue) { | ||||
|     return { | ||||
|         pass: (actualValue) === false, | ||||
|         message: 'expect false, actualValue is ' + actualValue | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertFalse; | ||||
| @ -0,0 +1,29 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertInstanceOf(actualValue, expected) { | ||||
|     if (Object.prototype.toString.call(actualValue) == '[object ' + expected[0] + ']') { | ||||
|         return { | ||||
|             pass: true | ||||
|         }; | ||||
|     } else { | ||||
|         return { | ||||
|             pass: false, | ||||
|             message: actualValue + ' is ' + Object.prototype.toString.call(actualValue) + 'not  ' + expected[0] | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default assertInstanceOf; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertLarger(actualValue, expected) { | ||||
|     return { | ||||
|         pass: (actualValue) > expected[0], | ||||
|         message: (actualValue) + ' is not larger than ' + expected[0] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertLarger; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertLargerOrEqual(actualValue, expected) { | ||||
|     return { | ||||
|         pass: (actualValue) >= expected[0], | ||||
|         message: (actualValue) + ' is not larger than ' + expected[0] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertLargerOrEqual; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertLess(actualValue, expected) { | ||||
|     return { | ||||
|         pass: (actualValue) < expected[0], | ||||
|         message: (actualValue) + ' is not less than ' + expected[0] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertLess; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertLessOrEqual(actualValue, expected) { | ||||
|     return { | ||||
|         pass: (actualValue) <= expected[0], | ||||
|         message: (actualValue) + ' is not less than ' + expected[0] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertLessOrEqual; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertNaN(actualValue) { | ||||
|     return { | ||||
|         pass: actualValue !== actualValue, | ||||
|         message: 'expect NaN, actualValue  is ' + actualValue | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertNaN; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
| * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| * you may not use this file except in compliance with the License. | ||||
| * You may obtain a copy of the License at | ||||
| * | ||||
| *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| * | ||||
| * Unless required by applicable law or agreed to in writing, software | ||||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| function assertNegUnlimited(actualValue) { | ||||
|     return { | ||||
|         pass: actualValue === Number.NEGATIVE_INFINITY, | ||||
|         message: 'Expected actualValue not to be -Infinity.  actualValue is,' + actualValue | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertNegUnlimited; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertNull(actualValue) { | ||||
|     return { | ||||
|         pass: (actualValue) === null, | ||||
|         message: 'expect null, actualValue is ' + (actualValue) | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertNull; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
| * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| * you may not use this file except in compliance with the License. | ||||
| * You may obtain a copy of the License at | ||||
| * | ||||
| *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| * | ||||
| * Unless required by applicable law or agreed to in writing, software | ||||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| function assertPosUnlimited(actualValue) { | ||||
|     return { | ||||
|         pass: actualValue === Number.POSITIVE_INFINITY, | ||||
|         message: 'Expected actualValue is POSITIVE_INFINITY.  actualValue is,' + actualValue | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertPosUnlimited; | ||||
| @ -0,0 +1,42 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import isPromiseLike from './isPromiseLike'; | ||||
| 
 | ||||
| function assertPromiseIsPending(actualPromise) { | ||||
|     if (!isPromiseLike(actualPromise)) { | ||||
|         return Promise.reject().then(function () { | ||||
|         }, function () { | ||||
|             return {pass: false, message: 'Expected not be called on a promise.'}; | ||||
|         }); | ||||
|     } | ||||
|     const helper = {}; | ||||
|     return Promise.race([actualPromise, Promise.resolve(helper)]).then( | ||||
|         function (got) { | ||||
|             return helper === got ? {pass: true, message: 'actualValue is isPending'} | ||||
|                 : { | ||||
|                     pass: false, | ||||
|                     message: 'expect isPending, actualValue is resolve' | ||||
|                 }; | ||||
|         }, | ||||
|         function () { | ||||
|             return { | ||||
|                 pass: false | ||||
|                 , message: 'expect isPending, actualValue is reject' | ||||
|             }; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| export default assertPromiseIsPending; | ||||
| @ -0,0 +1,40 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import isPromiseLike from './isPromiseLike'; | ||||
| 
 | ||||
| function assertPromiseIsRejected(actualPromise) { | ||||
|     if (!isPromiseLike(actualPromise)) { | ||||
|         return Promise.reject().then(function () { | ||||
|         }, function () { | ||||
|             return {pass: false, message: 'Expected not be called on a promise.'}; | ||||
|         }); | ||||
|     } | ||||
|     const helper = {}; | ||||
|     return Promise.race([actualPromise, Promise.resolve(helper)]).then( | ||||
|         function (got) { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: 'expect isRejected, but actualValue is ' | ||||
|                     + (helper === got ? 'isPending' : 'resolve') | ||||
|             }; | ||||
|         }, | ||||
|         function () { | ||||
|             return {pass: true, message: 'actualValue is isRejected'}; | ||||
|         } | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export default assertPromiseIsRejected; | ||||
| @ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import isPromiseLike from './isPromiseLike'; | ||||
| 
 | ||||
| function assertPromiseIsRejectedWith(actualPromise, expectedValue) { | ||||
| 
 | ||||
|     if (!isPromiseLike(actualPromise)) { | ||||
|         return Promise.reject().then(function () { | ||||
|         }, function () { | ||||
|             return {pass: false, message: 'Expected not be called on a promise.'}; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     function tips(passed) { | ||||
|         return ('Expected a promise ' + (passed ? 'not ' : '') + | ||||
|             'to be rejected with ' + JSON.stringify(expectedValue[0])); | ||||
|     } | ||||
| 
 | ||||
|     const helper = {}; | ||||
|     return Promise.race([actualPromise, Promise.resolve(helper)]).then( | ||||
|         function (got) { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: tips(false) + ' but actualValue is ' | ||||
|                     + (helper === got ? 'isPending' : 'resolve') | ||||
|             }; | ||||
|         }, | ||||
|         function (actualValue) { | ||||
|             if (JSON.stringify(actualValue) == JSON.stringify(expectedValue[0])) { | ||||
|                 return { | ||||
|                     pass: true, | ||||
|                     message: 'actualValue was rejected with ' + JSON.stringify(actualValue) + '.' | ||||
|                 }; | ||||
|             } else { | ||||
|                 return { | ||||
|                     pass: false, | ||||
|                     message: tips(false) + ' but it was rejected with ' + JSON.stringify(actualValue) + '.' | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export default assertPromiseIsRejectedWith; | ||||
| @ -0,0 +1,103 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import isPromiseLike from './isPromiseLike'; | ||||
| 
 | ||||
| function assertPromiseIsRejectedWithError(actualPromise, expectedValue) { | ||||
|     if (!isPromiseLike(actualPromise)) { | ||||
|         return Promise.reject().then(function () { | ||||
|         }, function () { | ||||
|             return {pass: false, message: 'Expected not be called on a promise.'}; | ||||
|         }); | ||||
|     } | ||||
|     const helper = {}; | ||||
|     return Promise.race([actualPromise, Promise.resolve(helper)]).then( | ||||
|         function (got) { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: 'Expected a promise to be rejected but actualValue is ' | ||||
|                     + (helper === got ? 'isPending' : 'resolve') | ||||
|             }; | ||||
|         }, | ||||
|         function (actualValue) { | ||||
|             return matchError(actualValue, expectedValue); | ||||
|         } | ||||
|     ); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| function matchError(actualValue, expectedValue) { | ||||
|     if (expectedValue.length == 1 && typeof expectedValue[0] === 'function') { | ||||
|         if (expectedValue[0].name === actualValue.__proto__.name) { | ||||
|             return {pass: true, message: 'actual error type is ' + actualValue.name + '.'}; | ||||
|         } | ||||
|         return { | ||||
|             pass: false, | ||||
|             message: 'except error type is ' + expectedValue[0].name + ',but actual is ' + actualValue.name + '.' | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     if (expectedValue.length == 1 && typeof expectedValue[0] === 'string') { | ||||
|         if (expectedValue[0] === actualValue.message) { | ||||
|             return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; | ||||
|         } | ||||
|         return { | ||||
|             pass: false, | ||||
|             message: 'except error message ' + expectedValue[0] + ',but actual is ' + actualValue.message + '.' | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     if (expectedValue.length == 1) { | ||||
|         return { | ||||
|             pass: false, | ||||
|             message: 'When only one parameter, it ' + | ||||
|                 'should be error type or error message.' | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name === actualValue.name) { | ||||
|         if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { | ||||
|             return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; | ||||
|         } else { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: 'except error message is ' + expectedValue[1] + ',but actual is ' + actualValue.message + '.' | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name !== actualValue.name) { | ||||
|         if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: 'except error type is ' + expectedValue[0].name + ',but actual is ' + actualValue.name + '.' | ||||
|             }; | ||||
|         } else { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: 'except error type and message are incorrect.' | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (expectedValue.length > 2) { | ||||
|         return { | ||||
|             pass: false, | ||||
|             message: 'Up to two parameters are supported.' | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default assertPromiseIsRejectedWithError; | ||||
| @ -0,0 +1,45 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import isPromiseLike from './isPromiseLike'; | ||||
| 
 | ||||
| function assertPromiseIsResolved(actualPromise) { | ||||
|     if (!isPromiseLike(actualPromise)) { | ||||
|         return Promise.reject().then(function () { | ||||
|         }, function () { | ||||
|             return {pass: false, message: 'Expected not be called on a promise.'}; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     const helper = {}; | ||||
|     return Promise.race([actualPromise, Promise.resolve(helper)]).then( | ||||
|         function (got) { | ||||
|             return helper === got ? { | ||||
|                 pass: false, | ||||
|                 message: 'expect resolve, actualValue is isPending' | ||||
|             } | ||||
|                 : {pass: true, message: 'actualValue is isResolved'}; | ||||
|         }, | ||||
|         function (rej) { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: 'Expected a promise to be resolved but it was ' + | ||||
|                     'rejected with ' + JSON.stringify(rej) + '.' | ||||
|             }; | ||||
|         } | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export default assertPromiseIsResolved; | ||||
| @ -0,0 +1,59 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import isPromiseLike from './isPromiseLike'; | ||||
| 
 | ||||
| function assertPromiseIsResolvedWith(actualPromise, expectedValue) { | ||||
|     if (!isPromiseLike(actualPromise)) { | ||||
|         return Promise.reject().then(function () { | ||||
|         }, function () { | ||||
|             return {pass: false, message: 'Expected not be called on a promise.'}; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     function tips(passed) { | ||||
|         return ( | ||||
|             'Expected a promise ' + (passed ? 'not ' : '') + | ||||
|             'to be resolved with ' + JSON.stringify(expectedValue[0])); | ||||
|     } | ||||
| 
 | ||||
|     const helper = {}; | ||||
|     return Promise.race([actualPromise, Promise.resolve(helper)]).then( | ||||
|         function (got) { | ||||
|             if (helper === got) { | ||||
|                 return {pass: false, message: 'expect resolve, actualValue is isPending'}; | ||||
|             } | ||||
|             if (JSON.stringify(got) == JSON.stringify(expectedValue[0])) { | ||||
|                 return { | ||||
|                     pass: true, | ||||
|                     message: 'actualValue was resolved with ' + JSON.stringify(got) + '.' | ||||
|                 }; | ||||
|             } | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: tips(false) + ' but it was resolved with ' + | ||||
|                     JSON.stringify(got) + '.' | ||||
|             }; | ||||
|         }, | ||||
|         function (rej) { | ||||
|             return { | ||||
|                 pass: false, | ||||
|                 message: tips(false) + ' but it was rejected with ' + JSON.stringify(rej) + '.' | ||||
|             }; | ||||
|         } | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export default assertPromiseIsResolvedWith; | ||||
| @ -0,0 +1,44 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertThrowError(actualValue, expected) { | ||||
|     let result = false; | ||||
|     let err; | ||||
|     if (typeof actualValue !== 'function') { | ||||
|         throw new Error('actualValue is not a function'); | ||||
|     } | ||||
|     try { | ||||
|         actualValue(); | ||||
|         return { | ||||
|             pass: result, | ||||
|             message: ' An error is not thrown while it is expected!' | ||||
|         }; | ||||
|     } catch (e) { | ||||
|         err = e; | ||||
|     } | ||||
| 
 | ||||
|     if (err instanceof Error) { | ||||
|         console.log(err.message); | ||||
|         if (err.message == expected[0]) { | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|     return { | ||||
|         pass: result, | ||||
|         message: 'expected throw failed , ' + err.message + ' is not ' + expected[0] | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertThrowError; | ||||
| @ -0,0 +1,23 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function assertUndefined(actualValue) { | ||||
|     return { | ||||
|         pass: undefined === (actualValue), | ||||
|         message: 'expect Undefined, actualValue is ' + (actualValue) | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export default assertUndefined; | ||||
| @ -0,0 +1,138 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class DeepTypeUtils { | ||||
|     static getType_(value) { | ||||
|        return Object.prototype.toString.apply(value); | ||||
|    } | ||||
|     static isA_(typeName, value) { | ||||
|         return this.getType_(value) === '[object ' + typeName + ']'; | ||||
|     } | ||||
|     static isAsymmetricEqualityTester_(obj) { | ||||
|         return obj ? this.isA_('Function', obj.asymmetricMatch) : false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 是否是function | ||||
|      * @param value | ||||
|      */ | ||||
|     static isFunction_(value) { | ||||
|         return this.isA_('Function', value); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 是否是undefined | ||||
|      * @param obj | ||||
|      */ | ||||
|     static isUndefined(obj) { | ||||
|         return obj === void 0; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 是否是Node | ||||
|      * @param obj | ||||
|      */ | ||||
|     static isDomNode(obj) { | ||||
|         return obj !== null && | ||||
|               typeof obj === 'object' && | ||||
|               typeof obj.nodeType === 'number' && | ||||
|               typeof obj.nodeName === 'string'; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 是否是promise对象 | ||||
|      * @param obj | ||||
|      */ | ||||
|     static isPromise (obj) { | ||||
|         return !!obj && obj.constructor === Promise; | ||||
|   }; | ||||
|     /** | ||||
|      *  是否是map对象 | ||||
|      * @param obj | ||||
|      */ | ||||
|     static isMap(obj) { | ||||
|         return ( | ||||
|             obj !== null && | ||||
|             typeof obj !== 'undefined' && | ||||
|             obj.constructor === Map | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 是否是set对象 | ||||
|      * @param obj 对象 | ||||
|      */ | ||||
|     static isSet(obj) { | ||||
|         return ( | ||||
|             obj !== null && | ||||
|             typeof obj !== 'undefined' && | ||||
|             obj.constructor === Set | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 对象是否有key属性 | ||||
|      * @param obj 对象 | ||||
|      * @param key 对象属性名称 | ||||
|      */ | ||||
|     static has(obj, key) { | ||||
|         return Object.prototype.hasOwnProperty.call(obj, key); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取对象的自有属性 | ||||
|      * @param obj 对象 | ||||
|      * @param isArray 是否是数组,[object Array] | ||||
|      */ | ||||
|     static keys(obj, isArray) { | ||||
|      const extraKeys = []; | ||||
|         // 获取对象所有属性
 | ||||
|      const  allKeys = this.getAllKeys(obj); | ||||
|         if (!isArray) { | ||||
|             return allKeys; | ||||
|         } | ||||
|         if (allKeys.length === 0) { | ||||
|             return allKeys; | ||||
|         } | ||||
|         for (const k of allKeys) { | ||||
|             if (typeof k === 'symbol' || !/^[0-9]+$/.test(k)) { | ||||
|                 extraKeys.push(k); | ||||
|             } | ||||
|         } | ||||
|         return extraKeys; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取obj对象的所有属性 | ||||
|      * @param obj obj对象 | ||||
|      */ | ||||
|     static getAllKeys(obj) { | ||||
|         const keys = []; | ||||
|         for (let key in obj) { | ||||
|             if(this.has(obj, key)) { | ||||
|                 keys.push(key); | ||||
|             } | ||||
|         } | ||||
|         const symbols = Object.getOwnPropertySymbols(obj); | ||||
|         for (const sym of symbols) { | ||||
|             if (obj.propertyIsEnumerable(sym)) { | ||||
|                 keys.push(sym); | ||||
|             } | ||||
|         } | ||||
|         return keys; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| export default DeepTypeUtils; | ||||
| @ -0,0 +1,311 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import DeepTypeUtils from './DeepTypeUtils' | ||||
| function assertDeepEquals(actualValue, expected) { | ||||
|     console.log('actualValue:' + actualValue + ',expected:' + expected[0]); | ||||
|     let result = eq(actualValue, expected[0],[], []) | ||||
|     let msg = logMsg(actualValue, expected[0]); | ||||
|     return { | ||||
|         pass: result, | ||||
|         message: msg | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 获取失败显示日志 | ||||
|  * @param actualValue 实际对象 | ||||
|  * @param expected 期待比较对象 | ||||
|  */ | ||||
| function logMsg(actualValue, expected) { | ||||
|     // 获取a的对象名称
 | ||||
|     const aClassName = Object.prototype.toString.call(actualValue); | ||||
|     const bClassName = Object.prototype.toString.call(expected); | ||||
|     let actualMsg; | ||||
|     let expectMsg; | ||||
|     if(aClassName == "[object Function]") { | ||||
|         actualMsg = "actualValue Function" | ||||
|     }else if(aClassName == "[object Promise]") { | ||||
|         actualMsg = "actualValue Promise" | ||||
|     }else if(aClassName == "[object Set]" || aClassName == "[object Map]") { | ||||
|         actualMsg = JSON.stringify(Array.from(actualValue));; | ||||
|     }else if(aClassName == "[object RegExp]") { | ||||
|         actualMsg = JSON.stringify(actualValue.source.replace("\\",""));; | ||||
|     } | ||||
|     else{ | ||||
|         actualMsg = JSON.stringify(actualValue); | ||||
|     } | ||||
|     if(bClassName == "[object Function]") { | ||||
|         expectMsg = "expected Function" | ||||
|     }else if(bClassName == "[object Promise]") { | ||||
|         expectMsg = "expected Promise" | ||||
|     }else if(aClassName == "[object Set]" || bClassName == "[object Map]") { | ||||
|         expectMsg = JSON.stringify(Array.from(expected)); | ||||
|     }else if(aClassName == "[object RegExp]") { | ||||
|         expectMsg = JSON.stringify(expected.source.replace("\\",""));; | ||||
|     } | ||||
|     else{ | ||||
|         expectMsg = JSON.stringify(expected); | ||||
|     } | ||||
|     return actualMsg + " is not deep equal " + expectMsg; | ||||
| } | ||||
| 
 | ||||
| function eq(a, b, aStack, bStack) { | ||||
|     let result = true; | ||||
|     console.log('a is:' + a + ',b is:' + b); | ||||
|     const asymmetricResult = asymmetricMatch_(a,b); | ||||
|     if (!DeepTypeUtils.isUndefined(asymmetricResult)) { | ||||
|         return asymmetricResult; | ||||
|     } | ||||
| 
 | ||||
|     if (a instanceof Error && b instanceof Error) { | ||||
|         result = a.message == b.message; | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     if (a === b) { | ||||
|         result = a !== 0 || 1 / a == 1 / b; | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     if (a === null || b === null) { | ||||
|         result = a === b; | ||||
|         return result; | ||||
|     } | ||||
|     // 获取a的对象名称
 | ||||
|     const aClassName = Object.prototype.toString.call(a); | ||||
|     const bClassName = Object.prototype.toString.call(b); | ||||
|     console.log('aClassName is:' + aClassName); | ||||
|     console.log('bClassName is:' + bClassName); | ||||
|     // 不同类型不同对象
 | ||||
|     if (aClassName != bClassName) { | ||||
|         return false; | ||||
|     } | ||||
|     // 俩个string对象
 | ||||
|     if(aClassName === '[object String]') { | ||||
|         result = a == String(b); | ||||
|         return result; | ||||
|     } | ||||
|     // 俩个Number对象
 | ||||
|     if(aClassName === '[object Number]') { | ||||
|         result = a != +a ? b != +b : a === 0 && b === 0 ? 1 / a == 1 / b : a == +b; | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     if(aClassName === '[object Date]' || aClassName === '[object Boolean]') { | ||||
|         result = +a == +b; | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     // 数组
 | ||||
|     if(aClassName === '[object ArrayBuffer]') { | ||||
|         return eq(new Uint8Array(a), new Uint8Array(b), aStack, bStack); | ||||
|     } | ||||
| 
 | ||||
|     // 正则表达式
 | ||||
|     if(aClassName === '[object RegExp]') { | ||||
|         return ( | ||||
|             a.source == b.source && | ||||
|             a.global == b.global && | ||||
|             a.multiline == b.multiline && | ||||
|             a.ignoreCase == b.ignoreCase | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     if (typeof a != 'object' || typeof b != 'object') { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     const aIsDomNode = DeepTypeUtils.isDomNode(a); | ||||
|     const bIsDomNode = DeepTypeUtils.isDomNode(b); | ||||
|     if (aIsDomNode && bIsDomNode) { | ||||
|         // At first try to use DOM3 method isEqualNode
 | ||||
|         result = a.isEqualNode(b); | ||||
|         return result; | ||||
|     } | ||||
|     if (aIsDomNode || bIsDomNode) { | ||||
|         return false; | ||||
|     } | ||||
|     const aIsPromise = DeepTypeUtils.isPromise(a); | ||||
|     const bIsPromise = DeepTypeUtils.isPromise(b); | ||||
|     if (aIsPromise && bIsPromise) { | ||||
|         return a === b; | ||||
|     } | ||||
|     let length = aStack.length; | ||||
|     while (length--) { | ||||
|         if (aStack[length] == a) { | ||||
|             return bStack[length] == b; | ||||
|         } | ||||
|     } | ||||
|     aStack.push(a); | ||||
|     bStack.push(b); | ||||
|     let size = 0; | ||||
| 
 | ||||
|     // 都是数组
 | ||||
|     if(aClassName == '[object Array]') { | ||||
|         const aLength = a.length; | ||||
|         const bLength = b.length; | ||||
|         if (aLength !== bLength) { | ||||
|             // 数组长度不同,不是同一个对象
 | ||||
|             return false; | ||||
|             } | ||||
|         for (let i = 0; i < aLength || i < bLength; i++) { | ||||
|             // 递归每一个元素是否相同
 | ||||
|             result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack) && result; | ||||
|         } | ||||
|         if (!result) { | ||||
|             return false; | ||||
|         } | ||||
|     } else if(DeepTypeUtils.isMap(a) && DeepTypeUtils.isMap(b)) { | ||||
|         if (a.size != b.size) { | ||||
|             return false; | ||||
|         } | ||||
|         const keysA = []; | ||||
|         const keysB = []; | ||||
|         a.forEach(function(valueA, keyA) { | ||||
|             keysA.push(keyA); | ||||
|         }); | ||||
|         b.forEach(function(valueB, keyB) { | ||||
|             keysB.push(keyB); | ||||
|         }); | ||||
|         const mapKeys = [keysA, keysB]; | ||||
|         const cmpKeys = [keysB, keysA]; | ||||
|         for (let i = 0; result && i < mapKeys.length; i++) { | ||||
|             const mapIter = mapKeys[i]; | ||||
|             const cmpIter = cmpKeys[i]; | ||||
| 
 | ||||
|             for (let j = 0; result && j < mapIter.length; j++) { | ||||
|                 const mapKey = mapIter[j]; | ||||
|                 const cmpKey = cmpIter[j]; | ||||
|                 const mapValueA = a.get(mapKey); | ||||
|                 let mapValueB; | ||||
|                 if ( | ||||
|                 DeepTypeUtils.isAsymmetricEqualityTester_(mapKey) || | ||||
|                 (DeepTypeUtils.isAsymmetricEqualityTester_(cmpKey) && | ||||
|                 eq(mapKey, cmpKey)) | ||||
|                 ) { | ||||
|                     mapValueB = b.get(cmpKey); | ||||
|                 } else { | ||||
|                     mapValueB = b.get(mapKey); | ||||
|                 } | ||||
|                 result = eq(mapValueA, mapValueB, aStack, bStack); | ||||
|             } | ||||
|         } | ||||
|         if (!result) { | ||||
|             return false; | ||||
|         } | ||||
|     } else if(DeepTypeUtils.isSet(a) && DeepTypeUtils.isSet(b)) { | ||||
|         if (a.size != b.size) { | ||||
|             return false; | ||||
|         } | ||||
|         const valuesA = []; | ||||
|         a.forEach(function(valueA) { | ||||
|             valuesA.push(valueA); | ||||
|         }); | ||||
|         const valuesB = []; | ||||
|         b.forEach(function(valueB) { | ||||
|             valuesB.push(valueB); | ||||
|         }); | ||||
|         const setPairs = [[valuesA, valuesB], [valuesB, valuesA]]; | ||||
|        const stackPairs = [[aStack, bStack], [bStack, aStack]]; | ||||
|         for (let i = 0; result && i < setPairs.length; i++) { | ||||
|             const baseValues = setPairs[i][0]; | ||||
|             const otherValues = setPairs[i][1]; | ||||
|             const baseStack = stackPairs[i][0]; | ||||
|             const otherStack = stackPairs[i][1]; | ||||
|             for (const baseValue of baseValues) { | ||||
|                 let found = false; | ||||
|                 for (let j = 0; !found && j < otherValues.length; j++) { | ||||
|                     const otherValue = otherValues[j]; | ||||
|                     const prevStackSize = baseStack.length; | ||||
|                     // 深度比较对象
 | ||||
|                     found = eq(baseValue, otherValue, baseStack, otherStack); | ||||
|                     if (!found && prevStackSize !== baseStack.length) { | ||||
|                         baseStack.splice(prevStackSize); | ||||
|                         otherStack.splice(prevStackSize); | ||||
|                     } | ||||
|                 } | ||||
|                 result = result && found; | ||||
|             } | ||||
|         } | ||||
|         if (!result) { | ||||
|             return false; | ||||
|         } | ||||
|     } else { | ||||
|         const aCtor = a.constructor, | ||||
|             bCtor = b.constructor; | ||||
|         if ( | ||||
|         aCtor !== bCtor && | ||||
|         DeepTypeUtils.isFunction_(aCtor) && | ||||
|         DeepTypeUtils.isFunction_(bCtor) && | ||||
|         a instanceof aCtor && | ||||
|         b instanceof bCtor && | ||||
|         !(aCtor instanceof aCtor && bCtor instanceof bCtor) | ||||
|         ) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // 获取对象所有的属性集合
 | ||||
|     const aKeys = DeepTypeUtils.keys(a, aClassName == '[object Array]'); | ||||
|     size = aKeys.length; | ||||
| 
 | ||||
|     // 俩个对象属性长度不一致, 俩对象不相同
 | ||||
|     if (DeepTypeUtils.keys(b, bClassName == '[object Array]').length !== size) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // 俩对象属性数量相同, 递归比较每个属性值得值
 | ||||
|     for (const key of aKeys) { | ||||
|         console.log('key is:' + key); | ||||
|         // b 没有 key 属性
 | ||||
|         if(!DeepTypeUtils.has(b, key)) { | ||||
|             result = false; | ||||
|             continue; | ||||
|         } | ||||
|         if (!eq(a[key], b[key], aStack, bStack)) { | ||||
|             result = false; | ||||
|         } | ||||
|     } | ||||
|     if (!result) { | ||||
|         return false; | ||||
|     } | ||||
|     aStack.pop(); | ||||
|     bStack.pop(); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| function asymmetricMatch_(a, b) { | ||||
|     const asymmetricA = DeepTypeUtils.isAsymmetricEqualityTester_(a); | ||||
|     const asymmetricB = DeepTypeUtils.isAsymmetricEqualityTester_(b); | ||||
| 
 | ||||
|     if (asymmetricA === asymmetricB) { | ||||
|         return undefined; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 获取对象的自有属性 | ||||
|  * | ||||
|  * @param obj 对象 | ||||
|  * @param isArray 是否是一个数组 | ||||
|  */ | ||||
| function keys(obj, isArray) { | ||||
|     const keys = []; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export default assertDeepEquals; | ||||
| @ -0,0 +1,32 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| function isPromiseLike(obj) { | ||||
|     return !!obj && isFunction_(obj.then); | ||||
| } | ||||
| 
 | ||||
| function isFunction_(value) { | ||||
|     return isA_('Function', value); | ||||
| } | ||||
| 
 | ||||
| function isA_(typeName, value) { | ||||
|     return getType_(value) === '[object ' + typeName + ']'; | ||||
| } | ||||
| 
 | ||||
| function getType_(value) { | ||||
|     return Object.prototype.toString.apply(value); | ||||
| } | ||||
| 
 | ||||
| export default isPromiseLike; | ||||
| @ -0,0 +1,116 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| const SUITES_KEY = 'suites'; | ||||
| const SPECS_KEY = 'items'; | ||||
| const DESCRIBE_KEY = 'describe'; | ||||
| const IT_KEY = 'it'; | ||||
| const PARAMS_KEY = 'params'; | ||||
| const STRESS_KEY = 'stress'; | ||||
| 
 | ||||
| class ObjectUtils { | ||||
|     static get(object, name, defaultValue) { | ||||
|         let result = defaultValue; | ||||
|         for (const key in object) { | ||||
|             if (key === name) { | ||||
|                 return object[key]; | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     static has(object, key) { | ||||
|         return Object.prototype.hasOwnProperty.call(object, key); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| class DataDriver { | ||||
|     constructor(attr) { | ||||
|         this.id = 'dataDriver'; | ||||
|         this.data = attr.data || {}; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|         this.suiteService = this.coreContext.getDefaultService('suite'); | ||||
|         this.specService = this.coreContext.getDefaultService('spec'); | ||||
|     } | ||||
| 
 | ||||
|     getSpecParams() { | ||||
|         let specParams = []; | ||||
|         let suiteDesc = this.suiteService.getCurrentRunningSuite().description; | ||||
|         let specDesc = this.specService.getCurrentRunningSpec().description; | ||||
|         let suites = ObjectUtils.get(this.data, SUITES_KEY, []); | ||||
|         for (const suiteItem of suites) { | ||||
|             let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); | ||||
|             if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { | ||||
|                 let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); | ||||
|                 for (const specItem of specs) { | ||||
|                     if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { | ||||
|                         return ObjectUtils.get(specItem, PARAMS_KEY, specParams); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return specParams; | ||||
|     } | ||||
| 
 | ||||
|     getSuiteParams() { | ||||
|         let suiteParams = {}; | ||||
|         let suiteDesc = this.suiteService.getCurrentRunningSuite().description; | ||||
|         let suites = ObjectUtils.get(this.data, SUITES_KEY, []); | ||||
|         for (const suiteItem of suites) { | ||||
|             let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); | ||||
|             if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { | ||||
|                 suiteParams = Object.assign({}, suiteParams, ObjectUtils.get(suiteItem, PARAMS_KEY, suiteParams)); | ||||
|             } | ||||
|         } | ||||
|         return suiteParams; | ||||
|     } | ||||
| 
 | ||||
|     getSpecStress(specDesc) { | ||||
|         let stress = 1; | ||||
|         let suiteDesc = this.suiteService.getCurrentRunningSuite().description; | ||||
|         let suites = ObjectUtils.get(this.data, SUITES_KEY, []); | ||||
|         for (const suiteItem of suites) { | ||||
|             let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); | ||||
|             if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { | ||||
|                 let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); | ||||
|                 for (const specItem of specs) { | ||||
|                     if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { | ||||
|                         let tempStress = ObjectUtils.get(specItem, STRESS_KEY, stress); | ||||
|                         return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return stress; | ||||
|     } | ||||
| 
 | ||||
|     getSuiteStress(suiteDesc) { | ||||
|         let stress = 1; | ||||
|         let suites = ObjectUtils.get(this.data, SUITES_KEY, []); | ||||
|         for (const suiteItem of suites) { | ||||
|             let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); | ||||
|             if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { | ||||
|                 let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress); | ||||
|                 return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; | ||||
|             } | ||||
|         } | ||||
|         return stress; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default DataDriver; | ||||
| @ -0,0 +1,81 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class ClassFilter { | ||||
|     constructor(suiteName, itName, params) { | ||||
|         this.suiteName = suiteName; | ||||
|         this.itName = itName; | ||||
|         this.params = params; | ||||
|     } | ||||
| 
 | ||||
|     filterSuite() { | ||||
|         return !this.params.split(',').map(item => item.split('#')[0]).map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); | ||||
|     } | ||||
| 
 | ||||
|     filterIt() { | ||||
|         let classArray = this.params.split(',') || []; | ||||
|         let suiteFilterResult = classArray.filter(item => !item.includes('#')).map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); | ||||
|         let itFilterResult = classArray.filter(item => item.includes('#')).map(item => item == (this.suiteName + '#' + this.itName)).reduce((pre, cur) => pre || cur, false); | ||||
|         return !(suiteFilterResult || itFilterResult); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| class NotClassFilter { | ||||
|     constructor(suiteName, itName, params) { | ||||
|         this.suiteName = suiteName; | ||||
|         this.itName = itName; | ||||
|         this.params = params; | ||||
|     } | ||||
| 
 | ||||
|     filterSuite() { | ||||
|         return this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); | ||||
|     } | ||||
| 
 | ||||
|     filterIt() { | ||||
|         return this.params.split(',').some(item => item == (this.suiteName + '#' + this.itName)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| class SuiteAndItNameFilter { | ||||
|     constructor(suiteName, itName, params) { | ||||
|         this.suiteName = suiteName; | ||||
|         this.itName = itName; | ||||
|         this.params = params; | ||||
|     } | ||||
| 
 | ||||
|     filterSuite() { | ||||
|         return !this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); | ||||
|     } | ||||
| 
 | ||||
|     filterIt() { | ||||
|         return !this.params.split(',').map(item => item == this.itName).reduce((pre, cur) => pre || cur, false); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class TestTypesFilter { | ||||
|     constructor(suiteName, itName, fi, params) { | ||||
|         this.suiteName = suiteName; | ||||
|         this.itName = itName; | ||||
|         this.params = params; | ||||
|         this.fi = fi; | ||||
|     } | ||||
| 
 | ||||
|     filterIt() { | ||||
|         return !((this.params === (this.fi & this.params)) || this.fi === 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter}; | ||||
| @ -0,0 +1,292 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter} from './Filter'; | ||||
| const STRESS_RULE = /^[1-9]\d*$/; | ||||
| 
 | ||||
| class ConfigService { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.supportAsync = false; | ||||
|         this.random = false; | ||||
|         this.filterValid = []; | ||||
|         this.filter = 0; | ||||
|         this.flag = false; | ||||
|         this.suite = null; | ||||
|         this.itName = null; | ||||
|         this.testType = null; | ||||
|         this.level = null; | ||||
|         this.size = null; | ||||
|         this.class = null; | ||||
|         this.notClass = null; | ||||
|         this.timeout = null; | ||||
|         // 遇错即停模式配置
 | ||||
|         this.breakOnError = false; | ||||
|         // 压力测试配置
 | ||||
|         this.stress = null; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|     } | ||||
| 
 | ||||
|     isNormalInteger(str) { | ||||
|         const n = Math.floor(Number(str)); | ||||
|         return n !== Infinity && String(n) === String(str) && n >= 0; | ||||
|     } | ||||
| 
 | ||||
|     getStress() { | ||||
|         if (this.stress === undefined || this.stress === '' || this.stress === null) { | ||||
|             return 1; | ||||
|         } | ||||
|         return !this.stress.match(STRESS_RULE) ? 1 : Number.parseInt(this.stress); | ||||
|     } | ||||
| 
 | ||||
|     basicParamValidCheck(params) { | ||||
|         let size = params.size; | ||||
|         if (size !== undefined && size !== '' && size !== null) { | ||||
|             let sizeArray = ['small', 'medium', 'large']; | ||||
|             if (sizeArray.indexOf(size) === -1) { | ||||
|                 this.filterValid.push('size:' + size); | ||||
|             } | ||||
|         } | ||||
|         let level = params.level; | ||||
|         if (level !== undefined && level !== '' && level !== null) { | ||||
|             let levelArray = ['0', '1', '2', '3', '4']; | ||||
|             if (levelArray.indexOf(level) === -1) { | ||||
|                 this.filterValid.push('level:' + level); | ||||
|             } | ||||
|         } | ||||
|         let testType = params.testType; | ||||
|         if (testType !== undefined && testType !== '' && testType !== null) { | ||||
|             let testTypeArray = ['function', 'performance', 'power', 'reliability', 'security', | ||||
|                 'global', 'compatibility', 'user', 'standard', 'safety', 'resilience']; | ||||
|             if (testTypeArray.indexOf(testType) === -1) { | ||||
|                 this.filterValid.push('testType:' + testType); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     filterParamValidCheck(params) { | ||||
|         let timeout = params.timeout; | ||||
|         if (timeout !== undefined && timeout !== '' && timeout !== null) { | ||||
|             if (!this.isNormalInteger(timeout)) { | ||||
|                 this.filterValid.push('timeout:' + timeout); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let paramKeys = ['dryRun', 'random', 'breakOnError', 'coverage']; | ||||
|         for (const key of paramKeys) { | ||||
|             if (params[key] !== undefined && params[key] !== 'true' && params[key] !== 'false') { | ||||
|                 this.filterValid.push(`${key}:${params[key]}`); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 压力测试参数验证,正整数
 | ||||
|         if (params.stress !== undefined && params.stress !== '' && params.stress !== null) { | ||||
|             if (!params.stress.match(STRESS_RULE)) { | ||||
|                 this.filterValid.push('stress:' + params.stress); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let nameRule = /^[A-Za-z]{1}[\w#,.]*$/; | ||||
|         let paramClassKeys = ['class', 'notClass']; | ||||
|         for (const key of paramClassKeys) { | ||||
|             if (params[key] !== undefined && params[key] !== '' && params[key] !== null) { | ||||
|                 let classArray = params[key].split(','); | ||||
|                 classArray.forEach(item => !item.match(nameRule) ? this.filterValid.push(`${key}:${params[key]}`) : null); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     setConfig(params) { | ||||
|         this.basicParamValidCheck(params); | ||||
|         this.filterParamValidCheck(params); | ||||
|         try { | ||||
|             this.class = params.class; | ||||
|             this.notClass = params.notClass; | ||||
|             this.flag = params.flag || {flag: false}; | ||||
|             this.suite = params.suite; | ||||
|             this.itName = params.itName; | ||||
|             this.filter = params.filter; | ||||
|             this.testType = params.testType; | ||||
|             this.level = params.level; | ||||
|             this.size = params.size; | ||||
|             this.timeout = params.timeout; | ||||
|             this.dryRun = params.dryRun; | ||||
|             this.breakOnError = params.breakOnError; | ||||
|             this.random = params.random === 'true' ? true : false; | ||||
|             this.stress = params.stress; | ||||
|             this.coverage = params.coverage; | ||||
|             this.filterParam = { | ||||
|                 testType: { | ||||
|                     'function': 1, | ||||
|                     'performance': 1 << 1, | ||||
|                     'power': 1 << 2, | ||||
|                     'reliability': 1 << 3, | ||||
|                     'security': 1 << 4, | ||||
|                     'global': 1 << 5, | ||||
|                     'compatibility': 1 << 6, | ||||
|                     'user': 1 << 7, | ||||
|                     'standard': 1 << 8, | ||||
|                     'safety': 1 << 9, | ||||
|                     'resilience': 1 << 10, | ||||
|                 }, | ||||
|                 level: { | ||||
|                     '0': 1 << 24, | ||||
|                     '1': 1 << 25, | ||||
|                     '2': 1 << 26, | ||||
|                     '3': 1 << 27, | ||||
|                     '4': 1 << 28, | ||||
|                 }, | ||||
|                 size: { | ||||
|                     'small': 1 << 16, | ||||
|                     'medium': 1 << 17, | ||||
|                     'large': 1 << 18, | ||||
|                 } | ||||
|             }; | ||||
|             this.parseParams(); | ||||
|         } catch (err) { | ||||
|             console.info('setConfig error: ' + err.message); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     parseParams() { | ||||
|         if (this.filter != null) { | ||||
|             return; | ||||
|         } | ||||
|         let testTypeFilter = 0; | ||||
|         let sizeFilter = 0; | ||||
|         let levelFilter = 0; | ||||
|         if (this.testType != null) { | ||||
|             testTypeFilter = this.testType.split(',') | ||||
|                 .map(item => this.filterParam.testType[item] || 0) | ||||
|                 .reduce((pre, cur) => pre | cur, 0); | ||||
|         } | ||||
|         if (this.level != null) { | ||||
|             levelFilter = this.level.split(',') | ||||
|                 .map(item => this.filterParam.level[item] || 0) | ||||
|                 .reduce((pre, cur) => pre | cur, 0); | ||||
|         } | ||||
|         if (this.size != null) { | ||||
|             sizeFilter = this.size.split(',') | ||||
|                 .map(item => this.filterParam.size[item] || 0) | ||||
|                 .reduce((pre, cur) => pre | cur, 0); | ||||
|         } | ||||
|         this.filter = testTypeFilter | sizeFilter | levelFilter; | ||||
|         console.info('filter params:' + this.filter); | ||||
|     } | ||||
| 
 | ||||
|     isCurrentSuite(description) { | ||||
|         if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { | ||||
|             let suiteArray = this.suite.split(','); | ||||
|             return suiteArray.indexOf(description) !== -1; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     filterSuite(currentSuiteName) { | ||||
|         let filterArray = []; | ||||
|         if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { | ||||
|             filterArray.push(new SuiteAndItNameFilter(currentSuiteName, '', this.suite)); | ||||
|         } | ||||
|         if (this.class !== undefined && this.class !== '' && this.class !== null) { | ||||
|             filterArray.push(new ClassFilter(currentSuiteName, '', this.class)); | ||||
|         } | ||||
|         if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { | ||||
|             filterArray.push(new NotClassFilter(currentSuiteName, '', this.notClass)); | ||||
|         } | ||||
| 
 | ||||
|         let result = filterArray.map(item => item.filterSuite()).reduce((pre, cur) => pre || cur, false); | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     filterDesc(currentSuiteName, desc, fi, coreContext) { | ||||
|         let filterArray = []; | ||||
|         if (this.itName !== undefined && this.itName !== '' && this.itName !== null) { | ||||
|             filterArray.push(new SuiteAndItNameFilter(currentSuiteName, desc, this.itName)); | ||||
|         } | ||||
|         if (this.class !== undefined && this.class !== '' && this.class !== null) { | ||||
|             filterArray.push(new ClassFilter(currentSuiteName, desc, this.class)); | ||||
|         } | ||||
|         if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { | ||||
|             filterArray.push(new NotClassFilter(currentSuiteName, desc, this.notClass)); | ||||
|         } | ||||
|         if (typeof (this.filter) !== 'undefined' && this.filter !== 0 && fi !== 0) { | ||||
|             filterArray.push(new TestTypesFilter('', '', fi, this.filter)); | ||||
|         } | ||||
|         let result = filterArray.map(item => item.filterIt()).reduce((pre, cur) => pre || cur, false); | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     isRandom() { | ||||
|         return this.random || false; | ||||
|     } | ||||
| 
 | ||||
|     isBreakOnError() { | ||||
|         return this.breakOnError !== 'true' ? false : true; | ||||
|     } | ||||
| 
 | ||||
|     setSupportAsync(value) { | ||||
|         this.supportAsync = value; | ||||
|     } | ||||
| 
 | ||||
|     isSupportAsync() { | ||||
|         return this.supportAsync; | ||||
|     } | ||||
| 
 | ||||
|     translateParams(parameters) { | ||||
|         const keySet = new Set([ | ||||
|             '-s class', '-s notClass', '-s suite', '-s itName', | ||||
|             '-s level', '-s testType', '-s size', '-s timeout', | ||||
|             '-s dryRun', '-s random', '-s breakOnError', '-s stress', | ||||
|             '-s coverage', 'class', 'notClass', 'suite', 'itName', | ||||
|             'level', 'testType', 'size', 'timeout', 'dryRun', 'random', | ||||
|             'breakOnError', 'stress', 'coverage' | ||||
|         ]); | ||||
|         let targetParams = {}; | ||||
|         for (const key in parameters) { | ||||
|             if (keySet.has(key)) { | ||||
|                 var newKey = key.replace("-s ", ""); | ||||
|                 targetParams[newKey] = parameters[key]; | ||||
|             } | ||||
|         } | ||||
|         return targetParams; | ||||
|     } | ||||
|     translateParamsToString(parameters) { | ||||
|         const keySet = new Set([ | ||||
|             '-s class', '-s notClass', '-s suite', '-s itName', | ||||
|             '-s level', '-s testType', '-s size', '-s timeout', | ||||
|             '-s dryRun', '-s random', '-s breakOnError', '-s stress', | ||||
|             '-s coverage','class', 'notClass', 'suite', 'itName', | ||||
|             'level', 'testType', 'size', 'timeout', 'dryRun', 'random', | ||||
|             'breakOnError', 'stress', 'coverage' | ||||
|         ]); | ||||
|         let targetParams = ''; | ||||
|         for (const key in parameters) { | ||||
|             if (keySet.has(key)) { | ||||
|                 targetParams += ' ' + key + ' ' + parameters[key]; | ||||
|             } | ||||
|         } | ||||
|         return targetParams.trim(); | ||||
|     } | ||||
| 
 | ||||
|     execute() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { | ||||
|     ConfigService | ||||
| }; | ||||
| @ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * Copyright (c) 2023 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import SysTestKit from "../kit/SysTestKit"; | ||||
| 
 | ||||
| export async function collectCoverageData() { | ||||
|     if (globalThis.__coverage__ === undefined) { | ||||
|         return; | ||||
|     } | ||||
|     const strJson = JSON.stringify(globalThis.__coverage__); | ||||
|     const strLen = strJson.length; | ||||
|     const maxLen = 500; | ||||
|     const maxCount = Math.floor(strLen / maxLen); | ||||
|     const OHOS_REPORT_COVERAGE_DATA = 'OHOS_REPORT_COVERAGE_DATA:'; | ||||
|     for (let count = 0; count <= maxCount; count++) { | ||||
|         await SysTestKit.print(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,88 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class SysTestKit { | ||||
| 
 | ||||
|     static delegator = null; | ||||
|     static systemTime = null; | ||||
| 
 | ||||
|     constructor() { | ||||
|         this.id = 'sysTestKit'; | ||||
|         this.index = 0; | ||||
|     } | ||||
| 
 | ||||
|     static actionStart(tag) { | ||||
|         console.info(JSON.stringify(tag)); | ||||
|         var message = '\n' + 'OHOS_REPORT_ACTIONSTART: ' + JSON.stringify(tag) + '\n'; | ||||
|         SysTestKit.print(message); | ||||
|         console.info(tag + ' actionStart print success'); | ||||
|     } | ||||
| 
 | ||||
|     static actionEnd(tag) { | ||||
|         console.info(JSON.stringify(tag)); | ||||
|         var message = '\n' + 'OHOS_REPORT_ACTIONEND: ' + JSON.stringify(tag) + '\n'; | ||||
|         SysTestKit.print(message); | ||||
|         console.info(tag + ' actionEnd print success'); | ||||
|     } | ||||
| 
 | ||||
|     static async existKeyword(keyword, timeout) { | ||||
|         let reg = new RegExp(/^[a-zA-Z0-9]{1,}$/) | ||||
|         if (!reg.test(keyword)) { | ||||
|             throw new Error('keyword must contain more than one string, and only letters and numbers are supported.') | ||||
|         } | ||||
|         timeout = timeout || 4; | ||||
| 
 | ||||
|         let searchResult = false; | ||||
|         let cmd = 'hilog -x | grep -i \'' + keyword + '\' | wc -l'; | ||||
|         await executePromise(cmd, timeout).then((data) => { | ||||
|             searchResult = data; | ||||
|         }); | ||||
|         return searchResult; | ||||
|     } | ||||
|     static async print(message) { | ||||
|         if ('printSync' in SysTestKit.delegator) { | ||||
|             console.debug(`printSync called ...`); | ||||
|             SysTestKit.delegator.printSync(message); | ||||
|         } else { | ||||
|             await SysTestKit.delegator.print(message); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     static async getRealTime() { | ||||
|         let currentTime = new Date().getTime(); | ||||
|         if (SysTestKit.systemTime !== null && SysTestKit.systemTime !== undefined) { | ||||
|             await SysTestKit.systemTime.getRealTime().then((time) => { | ||||
|                 console.info(`systemTime.getRealTime success data: ${JSON.stringify(time)}`); | ||||
|                 currentTime = time; | ||||
|             }).catch((error) => { | ||||
|                 console.error(`failed to systemTime.getRealTime because ${JSON.stringify(error)}`); | ||||
|             }); | ||||
|         } | ||||
|         return currentTime; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function executePromise(cmd, timeout) { | ||||
|     return new Promise((resolve, reject) => { | ||||
|         SysTestKit.delegator.executeShellCommand(cmd, timeout, | ||||
|             (error, data) => { | ||||
|                 console.info('existKeyword CallBack: err : ' + JSON.stringify(error)); | ||||
|                 console.info('existKeyword CallBack: data : ' + JSON.stringify(data)); | ||||
|                 resolve(parseInt(data.stdResult) > 3 ? true : false); | ||||
|             }); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| export default SysTestKit; | ||||
| @ -0,0 +1,122 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class ArgumentMatchers { | ||||
|     ANY = "<any>"; | ||||
|     ANY_STRING = "<any String>"; | ||||
|     ANY_BOOLEAN = "<any Boolean>"; | ||||
|     ANY_NUMBER = "<any Number>"; | ||||
|     ANY_OBJECT = "<any Object>"; | ||||
|     ANY_FUNCTION = "<any Function>"; | ||||
|     MATCH_REGEXS = "<match regexs>"; | ||||
| 
 | ||||
|     static any() { | ||||
|     } | ||||
| 
 | ||||
|     static anyString() { | ||||
|     } | ||||
| 
 | ||||
|     static anyBoolean() { | ||||
|     } | ||||
| 
 | ||||
|     static anyNumber() { | ||||
|     } | ||||
| 
 | ||||
|     static anyObj() { | ||||
|     } | ||||
| 
 | ||||
|     static anyFunction() { | ||||
|     } | ||||
| 
 | ||||
|     static matchRegexs() { | ||||
|         let regex = arguments[0]; | ||||
|         if (ArgumentMatchers.isRegExp(regex)) { | ||||
|             return regex; | ||||
|         } | ||||
|         throw Error("not a regex"); | ||||
|     } | ||||
| 
 | ||||
|     static isRegExp(value) { | ||||
|         return Object.prototype.toString.call(value) === "[object RegExp]"; | ||||
|     } | ||||
| 
 | ||||
|     matcheReturnKey() { | ||||
|         let arg = arguments[0]; | ||||
|         let regex = arguments[1]; | ||||
|         let stubSetKey = arguments[2]; | ||||
| 
 | ||||
|         if (stubSetKey && stubSetKey == this.ANY) { | ||||
|             return this.ANY; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof arg === "string" && !regex) { | ||||
|             return this.ANY_STRING; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof arg === "boolean" && !regex) { | ||||
|             return this.ANY_BOOLEAN; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof arg === "number" && !regex) { | ||||
|             return this.ANY_NUMBER; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof arg === "object" && !regex) { | ||||
|             return this.ANY_OBJECT; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof arg === "function" && !regex) { | ||||
|             return this.ANY_FUNCTION; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof arg === "string" && regex) { | ||||
|             return regex.test(arg); | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     matcheStubKey() { | ||||
|         let key = arguments[0]; | ||||
| 
 | ||||
|         if (key === ArgumentMatchers.any) { | ||||
|             return this.ANY; | ||||
|         } | ||||
| 
 | ||||
|         if (key === ArgumentMatchers.anyString) { | ||||
|             return this.ANY_STRING; | ||||
|         } | ||||
|         if (key === ArgumentMatchers.anyBoolean) { | ||||
|             return this.ANY_BOOLEAN; | ||||
|         } | ||||
|         if (key === ArgumentMatchers.anyNumber) { | ||||
|             return this.ANY_NUMBER; | ||||
|         } | ||||
|         if (key === ArgumentMatchers.anyObj) { | ||||
|             return this.ANY_OBJECT; | ||||
|         } | ||||
|         if (key === ArgumentMatchers.anyFunction) { | ||||
|             return this.ANY_FUNCTION; | ||||
|         } | ||||
| 
 | ||||
|         if (ArgumentMatchers.isRegExp(key)) { | ||||
|             return key; | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default ArgumentMatchers; | ||||
| @ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class ExtendInterface { | ||||
|     constructor(mocker) { | ||||
|         this.mocker = mocker; | ||||
|     } | ||||
| 
 | ||||
|     stub() { | ||||
|         this.params = arguments; | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     stubMockedCall(returnInfo) { | ||||
|         this.mocker.stubApply(this, this.params, returnInfo); | ||||
|     } | ||||
| 
 | ||||
|     afterReturn(value) { | ||||
|         this.stubMockedCall(function () { | ||||
|             return value; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     afterReturnNothing() { | ||||
|         this.stubMockedCall(function () { | ||||
|             return undefined; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     afterAction(action) { | ||||
|         this.stubMockedCall(action); | ||||
|     } | ||||
| 
 | ||||
|     afterThrow(msg) { | ||||
|         this.stubMockedCall(function () { | ||||
|             throw msg; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     clear() { | ||||
|         this.mocker.clear(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default ExtendInterface; | ||||
| @ -0,0 +1,256 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import ExtendInterface from "./ExtendInterface"; | ||||
| import VerificationMode from "./VerificationMode"; | ||||
| import ArgumentMatchers from "./ArgumentMatchers"; | ||||
| 
 | ||||
| class MockKit { | ||||
| 
 | ||||
|     constructor() { | ||||
|         this.mFunctions = []; | ||||
|         this.stubs = new Map(); | ||||
|         this.recordCalls = new Map(); | ||||
|         this.currentSetKey = null; | ||||
|         this.mockObj = null; | ||||
|         this.recordMockedMethod = new Map(); | ||||
|     } | ||||
| 
 | ||||
|     init() { | ||||
|         this.reset(); | ||||
|     } | ||||
| 
 | ||||
|     reset() { | ||||
|         this.mFunctions = []; | ||||
|         this.stubs = {}; | ||||
|         this.recordCalls = {}; | ||||
|         this.currentSetKey = null; | ||||
|         this.mockObj = null; | ||||
|         this.recordMockedMethod = new Map(); | ||||
|     } | ||||
| 
 | ||||
|     clearAll() { | ||||
|         this.reset(); | ||||
|         var props = Object.keys(this); | ||||
|         for (var i = 0; i < props.length; i++) { | ||||
|             delete this[props[i]]; | ||||
|         } | ||||
| 
 | ||||
|         var props = Object.getOwnPropertyNames(this); | ||||
|         for (var i = 0; i < props.length; i++) { | ||||
|             delete this[props[i]]; | ||||
|         } | ||||
|         for (var key in this) { | ||||
|             delete this[key]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     clear(obj) { | ||||
|         if (!obj) throw Error("Please enter an object to be cleaned"); | ||||
|         if (typeof (obj) != 'object') throw new Error('Not a object'); | ||||
|         this.recordMockedMethod.forEach(function (value, key, map) { | ||||
|             if (key) { | ||||
|                 obj[key] = value; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     ignoreMock(obj, method) { | ||||
|         if (typeof (obj) != 'object') throw new Error('Not a object'); | ||||
|         if (typeof (method) != 'function') throw new Error('Not a function'); | ||||
|         let og = this.recordMockedMethod.get(method.propName); | ||||
|         if (og) { | ||||
|             obj[method.propName] = og; | ||||
|             this.recordMockedMethod.set(method.propName, undefined); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     extend(dest, source) { | ||||
|         dest["stub"] = source["stub"]; | ||||
|         dest["afterReturn"] = source["afterReturn"]; | ||||
|         dest["afterReturnNothing"] = source["afterReturnNothing"]; | ||||
|         dest["afterAction"] = source["afterAction"]; | ||||
|         dest["afterThrow"] = source["afterThrow"]; | ||||
|         dest["stubMockedCall"] = source["stubMockedCall"]; | ||||
|         dest["clear"] = source["clear"]; | ||||
|         return dest; | ||||
|     } | ||||
| 
 | ||||
|     stubApply(f, params, returnInfo) { | ||||
|         let values = this.stubs.get(f); | ||||
|         if (!values) { | ||||
|             values = new Map(); | ||||
|         } | ||||
|         let key = params[0]; | ||||
|         if (typeof key == "undefined") { | ||||
|             key = "anonymous-mock-" + f.propName; | ||||
|         } | ||||
|         let matcher = new ArgumentMatchers(); | ||||
|         if (matcher.matcheStubKey(key)) { | ||||
|             key = matcher.matcheStubKey(key); | ||||
|             if (key) { | ||||
|                 this.currentSetKey = key; | ||||
|             } | ||||
|         } | ||||
|         values.set(key, returnInfo); | ||||
|         this.stubs.set(f, values); | ||||
|     } | ||||
| 
 | ||||
|     getReturnInfo(f, params) { | ||||
|         let values = this.stubs.get(f); | ||||
|         if (!values) { | ||||
|             return undefined; | ||||
|         } | ||||
|         let retrunKet = params[0]; | ||||
|         if (typeof retrunKet == "undefined") { | ||||
|             retrunKet = "anonymous-mock-" + f.propName; | ||||
|         } | ||||
|         let stubSetKey = this.currentSetKey; | ||||
| 
 | ||||
|         if (this.currentSetKey && (typeof (retrunKet) != "undefined")) { | ||||
|             retrunKet = stubSetKey; | ||||
|         } | ||||
|         let matcher = new ArgumentMatchers(); | ||||
|         if (matcher.matcheReturnKey(params[0], undefined, stubSetKey) && matcher.matcheReturnKey(params[0], undefined, stubSetKey) != stubSetKey) { | ||||
|             retrunKet = params[0]; | ||||
|         } | ||||
| 
 | ||||
|         values.forEach(function (value, key, map) { | ||||
|             if (ArgumentMatchers.isRegExp(key) && matcher.matcheReturnKey(params[0], key)) { | ||||
|                 retrunKet = key; | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         return values.get(retrunKet); | ||||
|     } | ||||
| 
 | ||||
|     findName(obj, value) { | ||||
|         let properties = this.findProperties(obj); | ||||
|         let name = null; | ||||
|         properties.forEach( | ||||
|             function (va1, idx, array) { | ||||
|                 if (obj[va1] === value) { | ||||
|                     name = va1; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     isFunctionFromPrototype(f, container, propName) { | ||||
|         if (container.constructor != Object && container.constructor.prototype !== container) { | ||||
|             return container.constructor.prototype[propName] === f; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     findProperties(obj, ...arg) { | ||||
|         function getProperty(new_obj) { | ||||
|             if (new_obj.__proto__ === null) { | ||||
|                 return []; | ||||
|             } | ||||
|             let properties = Object.getOwnPropertyNames(new_obj); | ||||
|             return [...properties, ...getProperty(new_obj.__proto__)]; | ||||
|         } | ||||
|         return getProperty(obj); | ||||
|     } | ||||
| 
 | ||||
|     recordMethodCall(originalMethod, args) { | ||||
|         Function.prototype.getName = function () { | ||||
|             return this.name || this.toString().match(/function\s*([^(]*)\(/)[1]; | ||||
|         }; | ||||
|         let name = originalMethod.getName(); | ||||
|         let arglistString = name + '(' + Array.from(args).toString() + ')'; | ||||
|         let records = this.recordCalls.get(arglistString); | ||||
|         if (!records) { | ||||
|             records = 0; | ||||
|         } | ||||
|         records++; | ||||
|         this.recordCalls.set(arglistString, records); | ||||
|     } | ||||
| 
 | ||||
|     mockFunc(originalObject, originalMethod) { | ||||
|         let tmp = this; | ||||
|         this.originalMethod = originalMethod; | ||||
|         let f = function () { | ||||
|             let args = arguments; | ||||
|             let action = tmp.getReturnInfo(f, args); | ||||
|             if (originalMethod) { | ||||
|                 tmp.recordMethodCall(originalMethod, args); | ||||
|             } | ||||
|             if (action) { | ||||
|                 return action.apply(this, args); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         f.container = null || originalObject; | ||||
|         f.original = originalMethod || null; | ||||
| 
 | ||||
|         if (originalObject && originalMethod) { | ||||
|             if (typeof (originalMethod) != 'function') throw new Error('Not a function'); | ||||
|             var name = this.findName(originalObject, originalMethod); | ||||
|             originalObject[name] = f; | ||||
|             this.recordMockedMethod.set(name, originalMethod); | ||||
|             f.propName = name; | ||||
|             f.originalFromPrototype = this.isFunctionFromPrototype(f.original, originalObject, f.propName); | ||||
|         } | ||||
|         f.mocker = this; | ||||
|         this.mFunctions.push(f); | ||||
|         this.extend(f, new ExtendInterface(this)); | ||||
|         return f; | ||||
|     } | ||||
| 
 | ||||
|     verify(methodName, argsArray) { | ||||
|         if (!methodName) { | ||||
|             throw Error("not a function name"); | ||||
|         } | ||||
|         let a = this.recordCalls.get(methodName + '(' + argsArray.toString() + ')'); | ||||
|         return new VerificationMode(a ? a : 0); | ||||
|     } | ||||
| 
 | ||||
|     mockObject(object) { | ||||
|         if (!object || typeof object === "string") { | ||||
|             throw Error(`this ${object} cannot be mocked`); | ||||
|         } | ||||
|         const _this = this; | ||||
|         let mockedObject = {}; | ||||
|         let keys = Reflect.ownKeys(object); | ||||
|         keys.filter(key => (typeof Reflect.get(object, key)) === 'function') | ||||
|             .forEach(key => { | ||||
|                 mockedObject[key] = object[key]; | ||||
|                 mockedObject[key] = _this.mockFunc(mockedObject, mockedObject[key]); | ||||
|             }); | ||||
|         return mockedObject; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function ifMockedFunction(f) { | ||||
|     if (Object.prototype.toString.call(f) != "[object Function]" && | ||||
|         Object.prototype.toString.call(f) != "[object AsyncFunction]") { | ||||
|         throw Error("not a function"); | ||||
|     } | ||||
|     if (!f.stub) { | ||||
|         throw Error("not a mock function"); | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| function when(f) { | ||||
|     if (ifMockedFunction(f)) { | ||||
|         return f.stub.bind(f); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export {MockKit, when}; | ||||
| @ -0,0 +1,49 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import {expect} from '../../interface'; | ||||
| 
 | ||||
| class VerificationMode { | ||||
|     constructor(times) { | ||||
|         this.doTimes = times; | ||||
|     } | ||||
| 
 | ||||
|     times(count) { | ||||
|         expect(count).assertEqual(this.doTimes); | ||||
|     } | ||||
| 
 | ||||
|     never() { | ||||
|         console.log(this.doTimes); | ||||
|         expect(0).assertEqual(this.doTimes); | ||||
|     } | ||||
| 
 | ||||
|     once() { | ||||
|         expect(1).assertEqual(this.doTimes); | ||||
|     } | ||||
| 
 | ||||
|     atLeast(count) { | ||||
|         if (count > this.doTimes) { | ||||
|             throw Error('failed ' + count + ' greater than the actual execution times of method'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     atMost(count) { | ||||
|         if (count < this.doTimes) { | ||||
|             throw Error('failed ' + count + ' less than the actual execution times of method'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default VerificationMode; | ||||
| @ -0,0 +1,148 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import SysTestKit from "../kit/SysTestKit"; | ||||
| import {collectCoverageData} from '../coverage/coverageCollect'; | ||||
| 
 | ||||
| class OhReport { | ||||
|     constructor(attr) { | ||||
|         this.delegator = attr.delegator; | ||||
|         this.abilityDelegatorArguments = attr.abilityDelegatorArguments; | ||||
|         this.id = 'report'; | ||||
|         this.index = 0; | ||||
|         this.duration = 0; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|         this.suiteService = this.coreContext.getDefaultService('suite'); | ||||
|         this.specService = this.coreContext.getDefaultService('spec'); | ||||
|     } | ||||
| 
 | ||||
|     taskStart() { | ||||
|     } | ||||
| 
 | ||||
|     async taskDone() { | ||||
|         if (this.abilityDelegatorArguments !== null) { | ||||
|             this.taskDoneTime = new Date().getTime(); | ||||
|             let summary = this.suiteService.getSummary(); | ||||
|             const configService = this.coreContext.getDefaultService('config'); | ||||
|             if (configService['coverage'] === 'true') { | ||||
|                 await collectCoverageData(); | ||||
|             } | ||||
|             let message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure; | ||||
|             message += ', Error: ' + summary.error; | ||||
|             message += ', Pass: ' + summary.pass; | ||||
|             message += ', Ignore: ' + summary.ignore; | ||||
|             message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n'; | ||||
|             let isHasError = summary.failure > 0 || summary.error > 0; | ||||
|             let config = this.coreContext.getDefaultService('config'); | ||||
|             if (config.isBreakOnError() && isHasError) { | ||||
|                 // 未执行全部说明
 | ||||
|                 message += '\n' + 'OHOS_REPORT_RESULT: breakOnError model, Stopping whole test suite if one specific test case failed or error' + '\n'; | ||||
|             } | ||||
|             message += 'OHOS_REPORT_STATUS: taskconsuming=' + summary.duration + '\n'; | ||||
|             console.info(message); | ||||
|             await SysTestKit.print(message); | ||||
|         } | ||||
|         console.info('report print success'); | ||||
|         this.delegator.finishTest('your test finished!!!', 0, () => { }); | ||||
|     } | ||||
| 
 | ||||
|     incorrectFormat() { | ||||
|         if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { | ||||
|             var value = this.coreContext.getDefaultService('config').filterValid; | ||||
|             var message = 'this param ' + value.join(',') + ' is invalid' + '\n'; | ||||
|             this.delegator.finishTest(message, 0, () => { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async suiteStart() { | ||||
|         if (this.abilityDelegatorArguments !== null) { | ||||
|             let message = '\n' + 'OHOS_REPORT_SUM: ' + this.suiteService.getCurrentRunningSuite().getSpecsNum(); | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description + '\n'; | ||||
|             console.info(message); | ||||
|             await SysTestKit.print(message); | ||||
|             console.info(this.suiteService.getCurrentRunningSuite().description + ' suiteStart print success'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async suiteDone() { | ||||
|         if (this.abilityDelegatorArguments !== null) { | ||||
|             let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: suiteconsuming=' + this.suiteService.getCurrentRunningSuite().duration + '\n'; | ||||
|             console.info(message); | ||||
|             await SysTestKit.print(message); | ||||
|             console.info(this.suiteService.getCurrentRunningSuite().description + ' suiteDone print success'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async specStart() { | ||||
|         if (this.abilityDelegatorArguments !== null) { | ||||
|             let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index); | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: stream='; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n'; | ||||
|             console.info(message); | ||||
|             await SysTestKit.print(message); | ||||
|             console.info(this.specService.currentRunningSpec.description + ' specStart start print success'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async specDone() { | ||||
|         if (this.abilityDelegatorArguments !== null) { | ||||
|             let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: current=' + (this.index); | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; | ||||
|             message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); | ||||
|             let errorMsg = ''; | ||||
|             if (this.specService.currentRunningSpec.error) { | ||||
|                 message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error.message; | ||||
|                 message += '\n' + 'OHOS_REPORT_STATUS: stream='; | ||||
|                 message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; | ||||
|                 message += '\n' + this.specService.currentRunningSpec.error.message; | ||||
|                 message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; | ||||
|                 message += '\n' + 'OHOS_REPORT_STATUS_CODE: -1' + '\n'; | ||||
|             } else if (this.specService.currentRunningSpec.result) { | ||||
|                 if (this.specService.currentRunningSpec.result.failExpects.length > 0) { | ||||
|                     this.specService.currentRunningSpec.result.failExpects.forEach(failExpect => { | ||||
|                         errorMsg = failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue)); | ||||
|                     }); | ||||
|                     message += '\n' + 'OHOS_REPORT_STATUS: stack=' + errorMsg; | ||||
|                     message += '\n' + 'OHOS_REPORT_STATUS: stream='; | ||||
|                     message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; | ||||
|                     message += '\n' + errorMsg + '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; | ||||
|                     message += '\n' + 'OHOS_REPORT_STATUS_CODE: -2' + '\n'; | ||||
|                 } else { | ||||
|                     message += '\n' + 'OHOS_REPORT_STATUS: stream='; | ||||
|                     message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; | ||||
|                     message += '\n' + 'OHOS_REPORT_STATUS_CODE: 0' + '\n'; | ||||
|                 } | ||||
|             } else { | ||||
|                 message += '\n'; | ||||
|             } | ||||
|             message += 'OHOS_REPORT_STATUS: consuming=' + this.specService.currentRunningSpec.duration + '\n'; | ||||
|             console.info(message); | ||||
|             await SysTestKit.print(message); | ||||
|             console.info(this.specService.currentRunningSpec.description + ' specDone end print success'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default OhReport; | ||||
| @ -0,0 +1,137 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| class ReportExtend { | ||||
|     constructor(fileModule) { | ||||
|         this.id = 'extend'; | ||||
|         this.fileModule = fileModule; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|         this.suiteService = this.coreContext.getDefaultService('suite'); | ||||
|     } | ||||
| 
 | ||||
|     taskStart() { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     taskDone() { | ||||
|         const report = { | ||||
|             tag: 'testsuites', | ||||
|             name: 'summary_report', | ||||
|             timestamp: new Date().toDateString(), | ||||
|             time: '1', | ||||
|             errors: 0, | ||||
|             failures: 0, | ||||
|             tests: 0, | ||||
|             children: [] | ||||
|         }; | ||||
|         const rootSuite = this.suiteService.rootSuite; | ||||
|         if (rootSuite && rootSuite.childSuites) { | ||||
|             for (let testsuite of rootSuite.childSuites) { | ||||
|                 let suiteReport = { | ||||
|                     tag: 'testsuite', | ||||
|                     name: testsuite['description'], | ||||
|                     errors: 0, | ||||
|                     tests: 0, | ||||
|                     failures: 0, | ||||
|                     time: '0.1', | ||||
|                     children: [] | ||||
|                 }; | ||||
|                 let specs = testsuite['specs']; | ||||
|                 for (let testcase of specs) { | ||||
|                     report.tests++; | ||||
|                     suiteReport.tests++; | ||||
|                     let caseReport = { | ||||
|                         tag: 'testcase', | ||||
|                         name: testcase['description'], | ||||
|                         status: 'run', | ||||
|                         time: '0.0', | ||||
|                         classname: testsuite['description'] | ||||
|                     }; | ||||
|                     if (testcase.error) { | ||||
|                         caseReport['result'] = false; | ||||
|                         caseReport['children'] = [{ | ||||
|                             tag: 'error', | ||||
|                             type: '', | ||||
|                             message: testcase.error.message | ||||
|                         }]; | ||||
|                         report.errors++; | ||||
|                         suiteReport.errors++; | ||||
|                     } else if (testcase.result.failExpects.length > 0) { | ||||
|                         caseReport['result'] = false; | ||||
|                         let message = ''; | ||||
|                         testcase.result.failExpects.forEach(failExpect => { | ||||
|                             message += failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue || '')) + ';'; | ||||
|                         }); | ||||
|                         caseReport['children'] = [{ | ||||
|                             tag: 'failure', | ||||
|                             type: '', | ||||
|                             message: message | ||||
|                         }]; | ||||
|                         report.failures++; | ||||
|                         suiteReport.failures++; | ||||
|                     } else { | ||||
|                         caseReport['result'] = true; | ||||
|                     } | ||||
|                     suiteReport.children.push(caseReport); | ||||
|                 } | ||||
|                 report.children.push(suiteReport); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let reportXml = '<?xml version="1.0" encoding="UTF-8"?>\n' + json2xml(report); | ||||
|         this.fileModule.writeText({ | ||||
|             uri: 'internal://app/report.xml', | ||||
|             text: reportXml, | ||||
|             success: function () { | ||||
|                 console.info('call success callback success'); | ||||
|             }, | ||||
|             fail: function (data, code) { | ||||
|                 console.info('call fail callback success:'); | ||||
|             }, | ||||
|             complete: function () { | ||||
|                 console.info('call complete callback success'); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function json2xml(json) { | ||||
|     let tagName; | ||||
|     let hasChildren = false; | ||||
|     let childrenStr = ''; | ||||
|     let attrStr = ''; | ||||
|     for (let key in json) { | ||||
|         if (key === 'tag') { | ||||
|             tagName = json[key]; | ||||
|         } else if (key === 'children') { | ||||
|             if (json[key].length > 0) { | ||||
|                 hasChildren = true; | ||||
|                 for (let child of json[key]) { | ||||
|                     childrenStr += json2xml(child); | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             attrStr += ` ${key}="${json[key]}"`; | ||||
|         } | ||||
|     } | ||||
|     let xml = `<${tagName}${attrStr}`; | ||||
|     xml += hasChildren ? `>${childrenStr}</${tagName}>` : '/>'; | ||||
|     return xml; | ||||
| } | ||||
| 
 | ||||
| export default ReportExtend; | ||||
| @ -0,0 +1,929 @@ | ||||
| /* | ||||
|  * Copyright (c) 2021-2022 Huawei Device Co., Ltd. | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| import SysTestKit from "./module/kit/SysTestKit"; | ||||
| 
 | ||||
| class AssertException extends Error { | ||||
|     constructor(message) { | ||||
|         super(); | ||||
|         this.name = "AssertException"; | ||||
|         this.message = message; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function getFuncWithArgsZero(func, timeout, isStressTest) { | ||||
|     return new Promise(async (resolve, reject) => { | ||||
|         let timer = null; | ||||
|         if (!isStressTest) { | ||||
|             timer = setTimeout(() => { | ||||
|                 reject(new Error('execute timeout ' + timeout + 'ms')); | ||||
|             }, timeout); | ||||
|         } | ||||
|         try { | ||||
|             await func(); | ||||
|         } catch (err) { | ||||
|             reject(err); | ||||
|         } | ||||
|         timer !== null ? clearTimeout(timer) : null; | ||||
|         resolve(); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function getFuncWithArgsOne(func, timeout, isStressTest) { | ||||
|     return new Promise(async (resolve, reject) => { | ||||
|         let timer = null; | ||||
|         if (!isStressTest) { | ||||
|             timer = setTimeout(() => { | ||||
|                 reject(new Error('execute timeout ' + timeout + 'ms')); | ||||
|             }, timeout);; | ||||
|         } | ||||
| 
 | ||||
|         function done() { | ||||
|             timer !== null ? clearTimeout(timer) : null; | ||||
|             resolve(); | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             await func(done); | ||||
|         } catch (err) { | ||||
|             timer !== null ? clearTimeout(timer) : null; | ||||
|             reject(err); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function getFuncWithArgsTwo(func, timeout, paramItem, isStressTest) { | ||||
|     return new Promise(async (resolve, reject) => { | ||||
|         let timer = null; | ||||
|         if (!isStressTest) { | ||||
|             timer = setTimeout(() => { | ||||
|                 reject(new Error('execute timeout ' + timeout + 'ms')); | ||||
|             }, timeout); | ||||
|         } | ||||
| 
 | ||||
|         function done() { | ||||
|             timer !== null ? clearTimeout(timer) : null; | ||||
|             resolve(); | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             await func(done, paramItem); | ||||
|         } catch (err) { | ||||
|             timer !== null ? clearTimeout(timer) : null; | ||||
|             reject(err); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function processFunc(coreContext, func) { | ||||
|     let argNames = ((func || '').toString() | ||||
|         .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '') | ||||
|         .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2] | ||||
|         .split(',') // split parameters
 | ||||
|         .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim())) | ||||
|         .filter(String); | ||||
|     let funcLen = func.length; | ||||
|     let processedFunc; | ||||
|     const config = coreContext.getDefaultService('config'); | ||||
|     config.setSupportAsync(true); | ||||
|     const timeout = + (config.timeout === undefined ? 5000 : config.timeout); | ||||
|     const isStressTest = (coreContext.getServices('dataDriver') !== undefined || config.getStress() > 1); | ||||
|     switch (funcLen) { | ||||
|         case 0: { | ||||
|             processedFunc = function () { | ||||
|                 return getFuncWithArgsZero(func, timeout, isStressTest); | ||||
|             }; | ||||
|             break; | ||||
|         } | ||||
|         case 1: { | ||||
|             if (argNames[0] === 'data') { | ||||
|                 processedFunc = function (paramItem) { | ||||
|                     func(paramItem); | ||||
|                 }; | ||||
|             } else { | ||||
|                 processedFunc = function () { | ||||
|                     return getFuncWithArgsOne(func, timeout, isStressTest); | ||||
|                 }; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         default: { | ||||
|             processedFunc = function (paramItem) { | ||||
|                 return getFuncWithArgsTwo(func, timeout, paramItem, isStressTest); | ||||
|             }; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return processedFunc; | ||||
| } | ||||
| 
 | ||||
| function secureRandomNumber() { | ||||
|     return crypto.randomBytes(8).readUInt32LE() / 0xffffffff; | ||||
| } | ||||
| 
 | ||||
| class SuiteService { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.rootSuite = new SuiteService.Suite({}); | ||||
|         this.currentRunningSuite = this.rootSuite; | ||||
|         this.suitesStack = [this.rootSuite]; | ||||
|     } | ||||
| 
 | ||||
|     describe(desc, func) { | ||||
|         const configService = this.coreContext.getDefaultService('config'); | ||||
|         if (configService.filterSuite(desc)) { | ||||
|             console.info('filter suite :' + desc); | ||||
|             return; | ||||
|         } | ||||
|         const suite = new SuiteService.Suite({description: desc}); | ||||
|         if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { | ||||
|             let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc); | ||||
|             for (let i = 1; i < suiteStress; i++) { | ||||
|                 this.currentRunningSuite.childSuites.push(suite); | ||||
|             } | ||||
|         } | ||||
|         this.currentRunningSuite.childSuites.push(suite); | ||||
|         this.currentRunningSuite = suite; | ||||
|         this.suitesStack.push(suite); | ||||
|         func.call(); | ||||
|         let childSuite = this.suitesStack.pop(); | ||||
|         if (this.suitesStack.length === 0) { | ||||
|             this.currentRunningSuite = childSuite; | ||||
|             this.suitesStack.push(childSuite); | ||||
|         } | ||||
|         if (this.suitesStack.length > 1) { | ||||
|             this.currentRunningSuite = this.suitesStack.pop(); | ||||
|         } else { | ||||
|             this.currentRunningSuite = this.suitesStack.pop(); | ||||
|             this.suitesStack.push(this.currentRunningSuite); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     beforeAll(func) { | ||||
|         this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func)); | ||||
|     } | ||||
| 
 | ||||
|     beforeEach(func) { | ||||
|         this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func)); | ||||
|     } | ||||
| 
 | ||||
|     afterAll(func) { | ||||
|         this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func)); | ||||
|     } | ||||
| 
 | ||||
|     afterEach(func) { | ||||
|         this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func)); | ||||
|     } | ||||
| 
 | ||||
|     getCurrentRunningSuite() { | ||||
|         return this.currentRunningSuite; | ||||
|     } | ||||
| 
 | ||||
|     setCurrentRunningSuite(suite) { | ||||
|         this.currentRunningSuite = suite; | ||||
|     } | ||||
| 
 | ||||
|     traversalResults(suite, obj, breakOnError) { | ||||
|         if (suite.childSuites.length === 0 && suite.specs.length === 0) { | ||||
|             return obj; | ||||
|         } | ||||
|         if (suite.specs.length > 0) { | ||||
|             for (const itItem of suite.specs) { | ||||
|                 obj.total++; | ||||
|                 if (breakOnError && (obj.error > 0 || obj.failure > 0)) { // breakOnError模式
 | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (itItem.error) { | ||||
|                     obj.error++; | ||||
|                 } else if (itItem.result.failExpects.length > 0) { | ||||
|                     obj.failure++; | ||||
|                 } else if (itItem.result.pass === true) { | ||||
|                     obj.pass++; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         obj.duration += suite.duration; | ||||
| 
 | ||||
|         if (suite.childSuites.length > 0) { | ||||
|             for (const suiteItem of suite.childSuites) { | ||||
|                 this.traversalResults(suiteItem, obj, breakOnError); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     getSummary() { | ||||
|         let suiteService = this.coreContext.getDefaultService('suite'); | ||||
|         let rootSuite = suiteService.rootSuite; | ||||
|         const specService = this.coreContext.getDefaultService('spec'); | ||||
|         const configService = this.coreContext.getDefaultService('config'); | ||||
|         let breakOnError = configService.isBreakOnError(); | ||||
|         let isError = specService.getStatus(); | ||||
|         let isBreaKOnError = breakOnError && isError; | ||||
|         let obj = {total: 0, failure: 0, error: 0, pass: 0, ignore: 0, duration: 0}; | ||||
|         for (const suiteItem of rootSuite.childSuites) { | ||||
|             this.traversalResults(suiteItem, obj, isBreaKOnError); | ||||
|         } | ||||
|         obj.ignore = obj.total - obj.pass - obj.failure - obj.error; | ||||
|         return obj; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|     } | ||||
| 
 | ||||
|     traversalSuites(suite, obj, configService) { | ||||
|         if (suite.childSuites.length === 0 && suite.specs.length === 0) { | ||||
|             return []; | ||||
|         } | ||||
|         if (suite.specs.length > 0) { | ||||
|             let itArray = []; | ||||
|             for (const itItem of suite['specs']) { | ||||
|                 if (!configService.filterDesc(suite.description, itItem.description, itItem.fi, null)) { | ||||
|                     itArray.push({'itName': itItem.description}); | ||||
|                 } | ||||
|             } | ||||
|             obj[suite.description] = itArray; | ||||
|         } | ||||
| 
 | ||||
|         if (suite.childSuites.length > 0) { | ||||
|             let suiteArray = []; | ||||
|             for (const suiteItem of suite.childSuites) { | ||||
|                 let suiteObj = {}; | ||||
|                 this.traversalSuites(suiteItem, suiteObj, configService); | ||||
|                 if (!configService.filterSuite(suiteItem.description)) { | ||||
|                     suiteArray.push(suiteObj); | ||||
|                 } | ||||
|             } | ||||
|             obj.suites = suiteArray; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async dryRun(abilityDelegator) { | ||||
|         const configService = this.coreContext.getDefaultService('config'); | ||||
|         let testSuitesObj = {}; | ||||
|         let suitesArray = []; | ||||
|         for (const suiteItem of this.rootSuite.childSuites) { | ||||
|             let obj = {}; | ||||
|             this.traversalSuites(suiteItem, obj, configService); | ||||
|             if (!configService.filterSuite(suiteItem.description)) { | ||||
|                 suitesArray.push(obj); | ||||
|             } | ||||
|         } | ||||
|         testSuitesObj['suites'] = suitesArray; | ||||
| 
 | ||||
|         let strJson = JSON.stringify(testSuitesObj); | ||||
|         let strLen = strJson.length; | ||||
|         let maxLen = 500; | ||||
|         let maxCount = Math.floor(strLen / maxLen); | ||||
| 
 | ||||
|         for (let count = 0; count <= maxCount; count++) { | ||||
|             await SysTestKit.print(strJson.substring(count * maxLen, (count + 1) * maxLen)); | ||||
|         } | ||||
|         console.info('dryRun print success'); | ||||
|         abilityDelegator.finishTest('dry run finished!!!', 0, () => { }); | ||||
|     } | ||||
| 
 | ||||
|     execute() { | ||||
|         const configService = this.coreContext.getDefaultService('config'); | ||||
|         if (configService.filterValid.length !== 0) { | ||||
|             this.coreContext.fireEvents('task', 'incorrectFormat'); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (configService.isRandom() && this.rootSuite.childSuites.length > 0) { | ||||
|             this.rootSuite.childSuites.sort(function () { | ||||
|                 return Math.random().toFixed(1) > 0.5 ? -1 : 1; | ||||
|             }); | ||||
|             this.currentRunningSuite = this.rootSuite.childSuites[0]; | ||||
|         } | ||||
| 
 | ||||
|         if (configService.isSupportAsync()) { | ||||
|             let asyncExecute = async () => { | ||||
|                 await this.coreContext.fireEvents('task', 'taskStart'); | ||||
|                 await this.rootSuite.asyncRun(this.coreContext); | ||||
|             }; | ||||
|             asyncExecute().then(async () => { | ||||
|                 await this.coreContext.fireEvents('task', 'taskDone'); | ||||
|             }); | ||||
|         } else { | ||||
|             this.coreContext.fireEvents('task', 'taskStart'); | ||||
|             this.rootSuite.run(this.coreContext); | ||||
|             this.coreContext.fireEvents('task', 'taskDone'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     apis() { | ||||
|         const _this = this; | ||||
|         return { | ||||
|             describe: function (desc, func) { | ||||
|                 return _this.describe(desc, func); | ||||
|             }, | ||||
|             beforeAll: function (func) { | ||||
|                 return _this.beforeAll(func); | ||||
|             }, | ||||
|             beforeEach: function (func) { | ||||
|                 return _this.beforeEach(func); | ||||
|             }, | ||||
|             afterAll: function (func) { | ||||
|                 return _this.afterAll(func); | ||||
|             }, | ||||
|             afterEach: function (func) { | ||||
|                 return _this.afterEach(func); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SuiteService.Suite = class { | ||||
|     constructor(attrs) { | ||||
|         this.description = attrs.description || ''; | ||||
|         this.childSuites = []; | ||||
|         this.specs = []; | ||||
|         this.beforeAll = []; | ||||
|         this.afterAll = []; | ||||
|         this.beforeEach = []; | ||||
|         this.afterEach = []; | ||||
|         this.duration = 0; | ||||
|     } | ||||
| 
 | ||||
|     pushSpec(spec) { | ||||
|         this.specs.push(spec); | ||||
|     } | ||||
| 
 | ||||
|     removeSpec(desc) { | ||||
|         this.specs = this.specs.filter((item, index) => { | ||||
|             return item.description !== desc; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     getSpecsNum() { | ||||
|         return this.specs.length; | ||||
|     } | ||||
| 
 | ||||
|     isRun(coreContext) { | ||||
|         const configService = coreContext.getDefaultService('config'); | ||||
|         const suiteService = coreContext.getDefaultService('suite'); | ||||
|         const specService = coreContext.getDefaultService('spec'); | ||||
|         let breakOnError = configService.isBreakOnError(); | ||||
|         let isError = specService.getStatus(); | ||||
|         return breakOnError && isError; | ||||
|     } | ||||
| 
 | ||||
|     run(coreContext) { | ||||
|         const suiteService = coreContext.getDefaultService('suite'); | ||||
|         suiteService.setCurrentRunningSuite(this); | ||||
|         if (this.description !== '') { | ||||
|             coreContext.fireEvents('suite', 'suiteStart', this); | ||||
|         } | ||||
|         this.runHookFunc('beforeAll'); | ||||
|         if (this.specs.length > 0) { | ||||
|             const configService = coreContext.getDefaultService('config'); | ||||
|             if (configService.isRandom()) { | ||||
|                 this.specs.sort(function () { | ||||
|                     return Math.random().toFixed(1) > 0.5 ? -1 : 1; | ||||
|                 }); | ||||
|             } | ||||
|             for (let spec in this.specs) { | ||||
|                 let isBreakOnError = this.isRun(coreContext); | ||||
|                 if (isBreakOnError) { | ||||
|                     break; | ||||
|                 } | ||||
|                 this.runHookFunc('beforeEach'); | ||||
|                 spec.run(coreContext); | ||||
|                 this.runHookFunc('afterEach'); | ||||
|             } | ||||
|         } | ||||
|         if (this.childSuites.length > 0) { | ||||
|             for (let suite in this.childSuites) { | ||||
|                 let isBreakOnError = this.isRun(coreContext); | ||||
|                 if (isBreakOnError) { | ||||
|                     break; | ||||
|                 } | ||||
|                 suite.run(coreContext); | ||||
|                 suiteService.setCurrentRunningSuite(suite); | ||||
|             } | ||||
|         } | ||||
|         this.runHookFunc('afterAll'); | ||||
|         if (this.description !== '') { | ||||
|             coreContext.fireEvents('suite', 'suiteDone'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async asyncRun(coreContext) { | ||||
|         const suiteService = coreContext.getDefaultService('suite'); | ||||
|         suiteService.setCurrentRunningSuite(this); | ||||
|         suiteService.suitesStack.push(this); | ||||
|         if (this.description !== '') { | ||||
|             await coreContext.fireEvents('suite', 'suiteStart', this); | ||||
|         } | ||||
|         await this.runAsyncHookFunc('beforeAll'); | ||||
|         if (this.specs.length > 0) { | ||||
|             const configService = coreContext.getDefaultService('config'); | ||||
|             if (configService.isRandom()) { | ||||
|                 this.specs.sort(function () { | ||||
|                     return Math.random().toFixed(1) > 0.5 ? -1 : 1; | ||||
|                 }); | ||||
|             } | ||||
|             for (let i = 0; i < this.specs.length; i++) { | ||||
|                 // 遇错即停模式,发现用例有问题,直接返回,不在执行后面的it
 | ||||
|                 let isBreakOnError = this.isRun(coreContext); | ||||
|                 if (isBreakOnError) { | ||||
|                     console.log("break description :" + this.description); | ||||
|                     break; | ||||
|                 } | ||||
|                 await this.runAsyncHookFunc('beforeEach'); | ||||
|                 await this.specs[i].asyncRun(coreContext); | ||||
|                 await this.runAsyncHookFunc('afterEach'); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (this.childSuites.length > 0) { | ||||
|             for (let i = 0; i < this.childSuites.length; i++) { | ||||
|                 // 遇错即停模式, 发现用例有问题,直接返回,不在执行后面的description
 | ||||
|                 let isBreakOnError = this.isRun(coreContext); | ||||
|                 if (isBreakOnError) { | ||||
|                     console.log("break description :" + this.description); | ||||
|                     break; | ||||
|                 } | ||||
|                 await this.childSuites[i].asyncRun(coreContext); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         await this.runAsyncHookFunc('afterAll'); | ||||
|         if (this.description !== '') { | ||||
|             await coreContext.fireEvents('suite', 'suiteDone'); | ||||
|             let childSuite = suiteService.suitesStack.pop(); | ||||
|             if (suiteService.suitesStack.length === 0) { | ||||
|                 suiteService.suitesStack.push(childSuite); | ||||
|             } | ||||
|             if (suiteService.suitesStack.length > 1) { | ||||
|                 suiteService.setCurrentRunningSuite(suiteService.suitesStack.pop()); | ||||
|             } else { | ||||
|                 let currentRunningSuite = suiteService.suitesStack.pop(); | ||||
|                 suiteService.setCurrentRunningSuite(currentRunningSuite); | ||||
|                 suiteService.suitesStack.push(currentRunningSuite); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     runHookFunc(hookName) { | ||||
|         if (this[hookName] && this[hookName].length > 0) { | ||||
|             this[hookName].forEach(func => { | ||||
|                 try { | ||||
|                     func(); | ||||
|                 } catch (e) { | ||||
|                     console.error(e); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     runAsyncHookFunc(hookName) { | ||||
|         if (this[hookName] && this[hookName].length > 0) { | ||||
|             return new Promise(async resolve => { | ||||
|                 for (let i = 0; i < this[hookName].length; i++) { | ||||
|                     try { | ||||
|                         await this[hookName][i](); | ||||
|                     } catch (e) { | ||||
|                         console.error(e); | ||||
|                     } | ||||
|                 } | ||||
|                 resolve(); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| class SpecService { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.totalTest = 0; | ||||
|         this.hasError = false; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|     } | ||||
| 
 | ||||
|     setCurrentRunningSpec(spec) { | ||||
|         this.currentRunningSpec = spec; | ||||
|     } | ||||
| 
 | ||||
|     setStatus(obj) { | ||||
|         this.hasError = obj; | ||||
|     } | ||||
| 
 | ||||
|     getStatus() { | ||||
|         return this.hasError; | ||||
|     } | ||||
| 
 | ||||
|     getTestTotal() { | ||||
|         return this.totalTest; | ||||
|     } | ||||
| 
 | ||||
|     getCurrentRunningSpec() { | ||||
|         return this.currentRunningSpec; | ||||
|     } | ||||
| 
 | ||||
|     it(desc, filter, func) { | ||||
|         const configService = this.coreContext.getDefaultService('config'); | ||||
|         const currentSuiteName = this.coreContext.getDefaultService('suite').getCurrentRunningSuite().description; | ||||
|         if (configService.filterDesc(currentSuiteName, desc, filter, this.coreContext)) { | ||||
|             console.info('filter it :' + desc); | ||||
|         } else { | ||||
|             let processedFunc = processFunc(this.coreContext, func); | ||||
|             const spec = new SpecService.Spec({description: desc, fi: filter, fn: processedFunc}); | ||||
|             const suiteService = this.coreContext.getDefaultService('suite'); | ||||
|             if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { | ||||
|                 let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc); | ||||
|                 for (let i = 1; i < specStress; i++) { | ||||
|                     this.totalTest++; | ||||
|                     suiteService.getCurrentRunningSuite().pushSpec(spec); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // dryRun 状态下不统计压力测试重复数据
 | ||||
|             if (configService['dryRun'] !== 'true') { | ||||
|                 let stress = configService.getStress(); // 命令配置压力测试
 | ||||
|                 console.info('stress length :' + stress); | ||||
|                 for (let i = 1; i < stress; i++) { | ||||
|                     this.totalTest++; | ||||
|                     suiteService.getCurrentRunningSuite().pushSpec(spec); | ||||
|                 } | ||||
|             } | ||||
|             this.totalTest++; | ||||
|             suiteService.getCurrentRunningSuite().pushSpec(spec); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     apis() { | ||||
|         const _this = this; | ||||
|         return { | ||||
|             it: function (desc, filter, func) { | ||||
|                 return _this.it(desc, filter, func); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| SpecService.Spec = class { | ||||
|     constructor(attrs) { | ||||
|         this.description = attrs.description || ''; | ||||
|         this.fi = attrs.fi; | ||||
|         this.fn = attrs.fn || function () { | ||||
|         }; | ||||
|         this.result = { | ||||
|             failExpects: [], | ||||
|             passExpects: [] | ||||
|         }; | ||||
|         this.error = undefined; | ||||
|         this.duration = 0; | ||||
|         this.startTime = 0; | ||||
|         this.isExecuted = false; // 当前用例是否执行
 | ||||
|     } | ||||
| 
 | ||||
|     setResult(coreContext) { | ||||
|         const specService = coreContext.getDefaultService('spec'); | ||||
|         if (this.result.failExpects.length > 0) { | ||||
|             this.result.pass = false; | ||||
|             specService.setStatus(true); | ||||
|         } else { | ||||
|             this.result.pass = true; | ||||
|         } | ||||
|         console.info('testcase ' + this.description + ' result:' + this.result.pass); | ||||
|     } | ||||
| 
 | ||||
|     run(coreContext) { | ||||
|         const specService = coreContext.getDefaultService('spec'); | ||||
|         specService.setCurrentRunningSpec(this); | ||||
|         coreContext.fireEvents('spec', 'specStart', this); | ||||
|         this.isExecuted = true; | ||||
|         try { | ||||
|             let dataDriver = coreContext.getServices('dataDriver'); | ||||
|             if (typeof dataDriver === 'undefined') { | ||||
|                 this.fn(); | ||||
|             } else { | ||||
|                 let suiteParams = dataDriver.dataDriver.getSuiteParams(); | ||||
|                 let specParams = dataDriver.dataDriver.getSpecParams(); | ||||
|                 console.info('[suite params] ' + JSON.stringify(suiteParams)); | ||||
|                 console.info('[spec params] ' + JSON.stringify(specParams)); | ||||
|                 if (this.fn.length === 0) { | ||||
|                     this.fn(); | ||||
|                 } else if (specParams.length === 0) { | ||||
|                     this.fn(suiteParams); | ||||
|                 } else { | ||||
|                     specParams.forEach(paramItem => this.fn(Object.assign({}, paramItem, suiteParams))); | ||||
|                 } | ||||
|             } | ||||
|             this.setResult(coreContext); | ||||
|         } catch (e) { | ||||
|             this.error = e; | ||||
|             specService.setStatus(true); | ||||
|         } | ||||
|         coreContext.fireEvents('spec', 'specDone', this); | ||||
|     } | ||||
| 
 | ||||
|     async asyncRun(coreContext) { | ||||
|         const specService = coreContext.getDefaultService('spec'); | ||||
|         specService.setCurrentRunningSpec(this); | ||||
| 
 | ||||
|         await coreContext.fireEvents('spec', 'specStart', this); | ||||
|         try { | ||||
|             let dataDriver = coreContext.getServices('dataDriver'); | ||||
|             if (typeof dataDriver === 'undefined') { | ||||
|                 await this.fn(); | ||||
|                 this.setResult(coreContext); | ||||
|             } else { | ||||
|                 let suiteParams = dataDriver.dataDriver.getSuiteParams(); | ||||
|                 let specParams = dataDriver.dataDriver.getSpecParams(); | ||||
|                 console.info('[suite params] ' + JSON.stringify(suiteParams)); | ||||
|                 console.info('[spec params] ' + JSON.stringify(specParams)); | ||||
|                 if (this.fn.length === 0) { | ||||
|                     await this.fn(); | ||||
|                     this.setResult(coreContext); | ||||
|                 } else if (specParams.length === 0) { | ||||
|                     await this.fn(suiteParams); | ||||
|                     this.setResult(coreContext); | ||||
|                 } else { | ||||
|                     for (const paramItem of specParams) { | ||||
|                         await this.fn(Object.assign({}, paramItem, suiteParams)); | ||||
|                         this.setResult(coreContext); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } catch (e) { | ||||
|             if (e instanceof AssertException) { | ||||
|                 this.fail = e; | ||||
|                 specService.setStatus(true); | ||||
|             } else { | ||||
|                 this.error = e; | ||||
|                 specService.setStatus(true); | ||||
|             } | ||||
|         } | ||||
|         this.isExecuted = true; | ||||
|         await coreContext.fireEvents('spec', 'specDone', this); | ||||
|     } | ||||
| 
 | ||||
|     filterCheck(coreContext) { | ||||
|         const specService = coreContext.getDefaultService('spec'); | ||||
|         specService.setCurrentRunningSpec(this); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     addExpectationResult(expectResult) { | ||||
|         if (this.result.failExpects.length === 0) { | ||||
|             this.result.failExpects.push(expectResult); | ||||
|         } | ||||
|         throw new AssertException(expectResult.message); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| class ExpectService { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|         this.matchers = {}; | ||||
|     } | ||||
| 
 | ||||
|     expect(actualValue) { | ||||
|         return this.wrapMatchers(actualValue); | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|         this.addMatchers(this.basicMatchers()); | ||||
|     } | ||||
| 
 | ||||
|     addMatchers(matchers) { | ||||
|         for (const matcherName in matchers) { | ||||
|             if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) { | ||||
|                 this.matchers[matcherName] = matchers[matcherName]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     basicMatchers() { | ||||
|         return { | ||||
|             assertTrue: function (actualValue) { | ||||
|                 return { | ||||
|                     pass: (actualValue) === true, | ||||
|                     message: 'expect true, actualValue is ' + actualValue | ||||
|                 }; | ||||
|             }, | ||||
|             assertEqual: function (actualValue, args) { | ||||
|                 return { | ||||
|                     pass: (actualValue) === args[0], | ||||
|                     expectValue: args[0], | ||||
|                     message: 'expect ' + actualValue + ' equals ' + args[0] | ||||
|                 }; | ||||
|             }, | ||||
|             assertThrow: function (actual, args) { | ||||
|                 const result = { | ||||
|                     pass: false | ||||
|                 }; | ||||
|                 if (typeof actual !== 'function') { | ||||
|                     result.message = 'toThrow\'s Actual should be a Function'; | ||||
|                 } else { | ||||
|                     let hasThrow = false; | ||||
|                     let throwError; | ||||
|                     try { | ||||
|                         actual(); | ||||
|                     } catch (e) { | ||||
|                         hasThrow = true; | ||||
|                         throwError = e; | ||||
|                     } | ||||
|                     if (!hasThrow) { | ||||
|                         result.message = 'function did not throw an exception'; | ||||
|                     } else if (throwError && throwError.message === args[0]) { | ||||
|                         result.pass = true; | ||||
|                     } else { | ||||
|                         result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`; | ||||
|                     } | ||||
|                 } | ||||
|                 return result; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     wrapMatchers(actualValue) { | ||||
|         const _this = this; | ||||
|         const wrappedMatchers = { | ||||
|             // 翻转标识
 | ||||
|             isNot: false, | ||||
| 
 | ||||
|             // 翻转方法
 | ||||
|             not: function () { | ||||
|                 this.isNot = true; | ||||
|                 return this; | ||||
|             } | ||||
|         }; | ||||
|         const specService = _this.coreContext.getDefaultService('spec'); | ||||
|         const currentRunningSpec = specService.getCurrentRunningSpec(); | ||||
|         for (const matcherName in this.matchers) { | ||||
|             let result = Object.prototype.hasOwnProperty.call(this.matchers, matcherName); | ||||
|             if (!result) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (matcherName.search('assertPromise') == 0) { | ||||
|                 wrappedMatchers[matcherName] = async function () { | ||||
|                     await _this.matchers[matcherName](actualValue, arguments).then(function (result) { | ||||
|                         if (wrappedMatchers.isNot) { | ||||
|                             result.pass = !result.pass; | ||||
|                         } | ||||
|                         result.actualValue = actualValue; | ||||
|                         result.checkFunc = matcherName; | ||||
|                         if (!result.pass) { | ||||
|                             currentRunningSpec.addExpectationResult(result); | ||||
|                         } | ||||
|                     }); | ||||
|                 }; | ||||
|             } else { | ||||
|                 wrappedMatchers[matcherName] = function () { | ||||
|                     const result = _this.matchers[matcherName](actualValue, arguments); | ||||
|                     if (wrappedMatchers.isNot) { | ||||
|                         result.pass = !result.pass; | ||||
|                     } | ||||
|                     result.actualValue = actualValue; | ||||
|                     result.checkFunc = matcherName; | ||||
|                     if (!result.pass) { | ||||
|                         currentRunningSpec.addExpectationResult(result); | ||||
|                     } | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
|         return wrappedMatchers; | ||||
|     } | ||||
| 
 | ||||
|     apis() { | ||||
|         const _this = this; | ||||
|         return { | ||||
|             expect: function (actualValue) { | ||||
|                 return _this.expect(actualValue); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| class ReportService { | ||||
|     constructor(attr) { | ||||
|         this.id = attr.id; | ||||
|     } | ||||
| 
 | ||||
|     init(coreContext) { | ||||
|         this.coreContext = coreContext; | ||||
|         this.specService = this.coreContext.getDefaultService('spec'); | ||||
|         this.suiteService = this.coreContext.getDefaultService('suite'); | ||||
|         this.duration = 0; | ||||
|     } | ||||
| 
 | ||||
|     taskStart() { | ||||
|         console.info('[start] start run suites'); | ||||
|     } | ||||
| 
 | ||||
|     async suiteStart() { | ||||
|         console.info('[suite start]' + this.suiteService.getCurrentRunningSuite().description); | ||||
|     } | ||||
| 
 | ||||
|     async specStart() { | ||||
|         console.info('start running case \'' + this.specService.currentRunningSpec.description + '\''); | ||||
|         this.index = this.index + 1; | ||||
|         let spec = this.specService.currentRunningSpec; | ||||
|         spec.startTime = await SysTestKit.getRealTime(); | ||||
|     } | ||||
| 
 | ||||
|     async specDone() { | ||||
|         let msg = ''; | ||||
|         let spec = this.specService.currentRunningSpec; | ||||
|         let suite = this.suiteService.currentRunningSuite; | ||||
|         spec.duration = await SysTestKit.getRealTime() - spec.startTime; | ||||
|         suite.duration += spec.duration; | ||||
|         if (spec.error) { | ||||
|             this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms'); | ||||
|             this.formatPrint('errorDetail', spec.error); | ||||
|         } else if (spec.result) { | ||||
|             if (spec.result.failExpects.length > 0) { | ||||
|                 this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms'); | ||||
|                 spec.result.failExpects.forEach(failExpect => { | ||||
|                     msg = failExpect.message || ('expect ' + failExpect.actualValue + ' ' | ||||
|                         + failExpect.checkFunc + ' ' + (failExpect.expectValue)); | ||||
|                     this.formatPrint('failDetail', msg); | ||||
|                 }); | ||||
|             } else { | ||||
|                 this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms'); | ||||
|             } | ||||
|         } | ||||
|         this.formatPrint(this.specService.currentRunningSpec.error, msg); | ||||
|     } | ||||
| 
 | ||||
|     suiteDone() { | ||||
|         let suite = this.suiteService.currentRunningSuite; | ||||
|         console.info(`[suite end] ${suite.description} consuming ${suite.duration} ms`); | ||||
|     } | ||||
| 
 | ||||
|     taskDone() { | ||||
|         let msg = ''; | ||||
|         let summary = this.suiteService.getSummary(); | ||||
|         msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error; | ||||
|         msg += ',pass ' + summary.pass + '; consuming ' + summary.duration + 'ms'; | ||||
|         console.info(msg); | ||||
|         console.info('[end] run suites end'); | ||||
|     } | ||||
| 
 | ||||
|     incorrectFormat() { | ||||
|         if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { | ||||
|             this.coreContext.getDefaultService('config').filterValid.forEach(function (item) { | ||||
|                 console.info('this param ' + item + ' is invalid'); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     formatPrint(type, msg) { | ||||
|         switch (type) { | ||||
|             case 'pass': | ||||
|                 console.info('[pass]' + msg); | ||||
|                 break; | ||||
|             case 'fail': | ||||
|                 console.info('[fail]' + msg); | ||||
|                 break; | ||||
|             case 'failDetail': | ||||
|                 console.info('[failDetail]' + msg); | ||||
|                 break; | ||||
|             case 'error': | ||||
|                 console.info('[error]' + msg); | ||||
|                 break; | ||||
|             case 'errorDetail': | ||||
|                 console.info('[errorDetail]' + msg); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     sleep(numberMillis) { | ||||
|         var now = new Date(); | ||||
|         var exitTime = now.getTime() + numberMillis; | ||||
|         while (true) { | ||||
|             now = new Date(); | ||||
|             if (now.getTime() > exitTime) { | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { | ||||
|     SuiteService, | ||||
|     SpecService, | ||||
|     ExpectService, | ||||
|     ReportService | ||||
| }; | ||||
							
								
								
									
										1
									
								
								entry/oh_modules/.ohpm/oh_modules/@ohos/hypium
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								entry/oh_modules/.ohpm/oh_modules/@ohos/hypium
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | ||||
| ../../@ohos+hypium@1.0.6/oh_modules/@ohos/hypium | ||||
							
								
								
									
										1
									
								
								entry/oh_modules/@ohos/hypium
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								entry/oh_modules/@ohos/hypium
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | ||||
| ../.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium | ||||
| @ -11,7 +11,6 @@ | ||||
|     "deliveryWithInstall": true, | ||||
|     "installationFree": false, | ||||
|     "pages": "$profile:main_pages", | ||||
| 
 | ||||
|     "abilities": [ | ||||
|       { | ||||
|         "name": "EntryAbility", | ||||
| @ -34,17 +33,12 @@ | ||||
|         ] | ||||
|       } | ||||
|     ], | ||||
|     "requestPermissions":[ | ||||
| 
 | ||||
|     "requestPermissions": [ | ||||
|       { | ||||
|         "name": "ohos.permission.INTERNET" | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.GET_NETWORK_INFO" | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.CAMERA", | ||||
| 
 | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.GET_WIFI_INFO" | ||||
| @ -70,32 +64,32 @@ | ||||
|       { | ||||
|         "name": "ohos.permission.MEDIA_LOCATION" | ||||
|       }, | ||||
|        { | ||||
|        "name": "ohos.permission.WRITE_MEDIA" | ||||
|        }, | ||||
|        { | ||||
|        "name": "ohos.permission.READ_MEDIA" | ||||
|        }, | ||||
| //      { | ||||
| //        "name": "ohos.permission.READ_MEDIA", | ||||
| //        "reason": "$string:module_desc", | ||||
| //        "usedScene": { | ||||
| //          "abilities": [ | ||||
| //            "MainAbility" | ||||
| //          ], | ||||
| //          "when": "always" | ||||
| //        } | ||||
| //      }, | ||||
| //      { | ||||
| //        "name": "ohos.permission.WRITE_MEDIA", | ||||
| //        "reason": "$string:module_desc", | ||||
| //        "usedScene": { | ||||
| //          "abilities": [ | ||||
| //            "MainAbility" | ||||
| //          ], | ||||
| //          "when": "always" | ||||
| //        } | ||||
| //      }, | ||||
|       { | ||||
|         "name": "ohos.permission.WRITE_MEDIA" | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.READ_MEDIA" | ||||
|       }, | ||||
|       //      { | ||||
|       //        "name": "ohos.permission.READ_MEDIA", | ||||
|       //        "reason": "$string:module_desc", | ||||
|       //        "usedScene": { | ||||
|       //          "abilities": [ | ||||
|       //            "MainAbility" | ||||
|       //          ], | ||||
|       //          "when": "always" | ||||
|       //        } | ||||
|       //      }, | ||||
|       //      { | ||||
|       //        "name": "ohos.permission.WRITE_MEDIA", | ||||
|       //        "reason": "$string:module_desc", | ||||
|       //        "usedScene": { | ||||
|       //          "abilities": [ | ||||
|       //            "MainAbility" | ||||
|       //          ], | ||||
|       //          "when": "always" | ||||
|       //        } | ||||
|       //      }, | ||||
|       { | ||||
|         "name": "ohos.permission.FILE_ACCESS_MANAGER", | ||||
|         "reason": "$string:module_desc", | ||||
|  | ||||
| @ -37,14 +37,6 @@ | ||||
|       { | ||||
|         "name": "ohos.permission.INTERNET" | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.GET_WIFI_INFO" | ||||
|       },  { | ||||
|         "name": "ohos.permission.INTERNET" | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.GET_WIFI_INFO", | ||||
|       }, | ||||
|       { | ||||
|         "name": "ohos.permission.DISTRIBUTED_DATASYNC", | ||||
|       }, | ||||
|  | ||||
							
								
								
									
										1
									
								
								material/ac/8da748c94a6f4d36b142a3edc090dc40
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								material/ac/8da748c94a6f4d36b142a3edc090dc40
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| <EFBFBD><EFBFBD>2\&3<><06><> <20><>¢<EFBFBD> | ||||
							
								
								
									
										
											BIN
										
									
								
								material/ce/bc943325cea34e90a617b11ef6887551
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								material/ce/bc943325cea34e90a617b11ef6887551
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								material/fd/0/dfc5f63f37634c3facdbae6dba056f8c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								material/fd/0/dfc5f63f37634c3facdbae6dba056f8c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| σΣT’&ΗcFw*¬Χ'aυ | ||||
							
								
								
									
										1
									
								
								material/fd/1/3ddea8591dce46e2a2417929f4c58457
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								material/fd/1/3ddea8591dce46e2a2417929f4c58457
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| \<5C><><EFBFBD>P,<2C>{<0E>U<EFBFBD><55><EFBFBD>"<22> | ||||
							
								
								
									
										1
									
								
								material/fd/2/184135aff5914321aece4570bbb31ed6
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								material/fd/2/184135aff5914321aece4570bbb31ed6
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| ■╕7╙▄и⌠╣≤Жv(еБ╕ | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user