From be332faa7c9fd4815dff9979465190edd0cfed1b Mon Sep 17 00:00:00 2001 From: yuanchao Date: Thu, 25 Aug 2022 18:47:49 +0800 Subject: [PATCH] hypium Signed-off-by: Signed-off-by: yuanchao --- .../demo/SensorSimulateDemo/.gitignore | 5 + .../demo/SensorSimulateDemo/README.md | 1 + .../SensorSimulateDemo/build-profile.json5 | 27 + .../demo/SensorSimulateDemo/entry/.gitignore | 4 + .../entry/build-profile.json5 | 14 + .../SensorSimulateDemo/entry/hvigorfile.js | 2 + .../SensorSimulateDemo/entry/package.json | 13 + .../entry/src/main/config.json | 66 ++ .../entry/src/main/ets/MainAbility/app.ets | 8 + .../src/main/ets/MainAbility/pages/index.ets | 17 + .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../entry/src/ohosTest/config.json | 67 ++ .../src/ohosTest/ets/TestAbility/app.ets | 18 + .../ohosTest/ets/TestAbility/pages/index.ets | 35 + .../ets/TestRunner/OpenHarmonyTestRunner.ts | 68 ++ .../entry/src/ohosTest/ets/test/List.test.ets | 5 + .../src/ohosTest/ets/test/Sensormock.test.ets | 188 +++++ .../resources/base/element/string.json | 12 + .../ohosTest/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../demo/SensorSimulateDemo/hvigorfile.js | 2 + .../demo/SensorSimulateDemo/package.json | 17 + Ability/Sensormock/hypium/LICENSE | 177 +++++ Ability/Sensormock/hypium/README.OpenSource | 11 + Ability/Sensormock/hypium/README.md | 152 ++++ Ability/Sensormock/hypium/index.d.ts | 122 +++ Ability/Sensormock/hypium/index.ets | 117 +++ Ability/Sensormock/hypium/index.js | 117 +++ Ability/Sensormock/hypium/package.json | 50 ++ Ability/Sensormock/hypium/src/Constant.js | 47 ++ Ability/Sensormock/hypium/src/core.js | 150 ++++ Ability/Sensormock/hypium/src/event.js | 94 +++ Ability/Sensormock/hypium/src/interface.js | 65 ++ .../hypium/src/module/assert/ExpectExtend.js | 62 ++ .../hypium/src/module/assert/assertClose.js | 41 + .../hypium/src/module/assert/assertContain.js | 35 + .../hypium/src/module/assert/assertFail.js | 23 + .../hypium/src/module/assert/assertFalse.js | 23 + .../src/module/assert/assertInstanceOf.js | 29 + .../hypium/src/module/assert/assertLarger.js | 23 + .../hypium/src/module/assert/assertLess.js | 23 + .../hypium/src/module/assert/assertNull.js | 23 + .../src/module/assert/assertThrowError.js | 44 ++ .../src/module/assert/assertUndefined.js | 23 + .../hypium/src/module/assert/isPromiseLike.js | 32 + .../hypium/src/module/config/DataDriver.js | 116 +++ .../hypium/src/module/config/Filter.js | 81 ++ .../hypium/src/module/config/configService.js | 269 +++++++ .../hypium/src/module/kit/SysTestKit.js | 65 ++ .../src/module/mock/ArgumentMatchers.js | 122 +++ .../hypium/src/module/mock/ExtendInterface.js | 57 ++ .../hypium/src/module/mock/MockKit.js | 281 +++++++ .../src/module/mock/VerificationMode.js | 49 ++ .../hypium/src/module/report/OhReport.js | 126 ++++ .../hypium/src/module/report/ReportExtend.js | 137 ++++ Ability/Sensormock/hypium/src/service.js | 702 ++++++++++++++++++ 57 files changed, 4081 insertions(+) create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/.gitignore create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/README.md create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5 create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5 create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/media/icon.png create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/config.json create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/app.ets create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestAbility/pages/index.ets create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/media/icon.png create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/hvigorfile.js create mode 100644 Ability/Sensormock/demo/SensorSimulateDemo/package.json create mode 100644 Ability/Sensormock/hypium/LICENSE create mode 100644 Ability/Sensormock/hypium/README.OpenSource create mode 100644 Ability/Sensormock/hypium/README.md create mode 100644 Ability/Sensormock/hypium/index.d.ts create mode 100644 Ability/Sensormock/hypium/index.ets create mode 100644 Ability/Sensormock/hypium/index.js create mode 100644 Ability/Sensormock/hypium/package.json create mode 100644 Ability/Sensormock/hypium/src/Constant.js create mode 100644 Ability/Sensormock/hypium/src/core.js create mode 100644 Ability/Sensormock/hypium/src/event.js create mode 100644 Ability/Sensormock/hypium/src/interface.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertClose.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertContain.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertFail.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertFalse.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertLarger.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertLess.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertNull.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertThrowError.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/assertUndefined.js create mode 100644 Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js create mode 100644 Ability/Sensormock/hypium/src/module/config/DataDriver.js create mode 100644 Ability/Sensormock/hypium/src/module/config/Filter.js create mode 100644 Ability/Sensormock/hypium/src/module/config/configService.js create mode 100644 Ability/Sensormock/hypium/src/module/kit/SysTestKit.js create mode 100644 Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js create mode 100644 Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js create mode 100644 Ability/Sensormock/hypium/src/module/mock/MockKit.js create mode 100644 Ability/Sensormock/hypium/src/module/mock/VerificationMode.js create mode 100644 Ability/Sensormock/hypium/src/module/report/OhReport.js create mode 100644 Ability/Sensormock/hypium/src/module/report/ReportExtend.js create mode 100644 Ability/Sensormock/hypium/src/service.js diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/.gitignore b/Ability/Sensormock/demo/SensorSimulateDemo/.gitignore new file mode 100644 index 00000000..91d237bb --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/local.properties +/.idea +**/build +/.hvigor \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/README.md b/Ability/Sensormock/demo/SensorSimulateDemo/README.md new file mode 100644 index 00000000..ecae5f8f --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/README.md @@ -0,0 +1 @@ +####传感器模拟的使用说明 \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5 b/Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5 new file mode 100644 index 00000000..3854f71f --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/build-profile.json5 @@ -0,0 +1,27 @@ +{ + "app": { + "signingConfigs": [], + "compileSdkVersion": 8, + "compatibleSdkVersion": 8, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore b/Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore new file mode 100644 index 00000000..5a6ba80f --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.preview +/build +/.cxx \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5 b/Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5 new file mode 100644 index 00000000..cfdc90f8 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/build-profile.json5 @@ -0,0 +1,14 @@ +{ + "apiType": 'faMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + "runtimeOS": "HarmonyOS" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js b/Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js new file mode 100644 index 00000000..bcec4c99 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyHapTasks diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json new file mode 100644 index 00000000..c4e988f3 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/package.json @@ -0,0 +1,13 @@ +{ + "name": "entry", + "version": "1.0.0", + "ohos": { + "org": "huawei", + "buildTool": "hvigor", + "directoryLevel": "module" + }, + "description": "example description", + "repository": {}, + "license": "ISC", + "dependencies": {} +} diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json new file mode 100644 index 00000000..4f523496 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/config.json @@ -0,0 +1,66 @@ +{ + "app": { + "bundleName": "com.example.sensorsimulatedemo", + "vendor": "example", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.entry", + "name": ".entry", + "mainAbility": ".MainAbility", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry", + "installationFree": false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "formsEnabled": false, + "name": ".MainAbility", + "srcLanguage": "ets", + "srcPath": "MainAbility", + "icon": "$media:icon", + "description": "$string:MainAbility_desc", + "label": "$string:MainAbility_label", + "type": "page", + "visible": true, + "launchType": "standard" + } + ], + "js": [ + { + "mode": { + "syntax": "ets", + "type": "pageAbility" + }, + "pages": [ + "pages/index" + ], + "name": ".MainAbility", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets new file mode 100644 index 00000000..b7a0995c --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/app.ets @@ -0,0 +1,8 @@ +export default { + onCreate() { + console.info('Application onCreate') + }, + onDestroy() { + console.info('Application onDestroy') + }, +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets new file mode 100644 index 00000000..d6ca48cf --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/ets/MainAbility/pages/index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World' + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..1bbc9aa9 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..490210a3 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "description" + }, + { + "name": "MainAbility_desc", + "value": "description" + }, + { + "name": "MainAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/media/icon.png b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 00000000..1f5bcf0a --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,68 @@ +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s package', '-s dryRun' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key] + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)) +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info('OpenHarmonyTestRunner OnPrepare') + } + + onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + var testAbilityName = abilityDelegatorArguments.parameters['-p'] + '.TestAbility' + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a ' + testAbilityName + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + var debug = abilityDelegatorArguments.parameters["-D"] + if (debug == 'true') + { + cmd += ' -D' + } + console.info('cmd : '+cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun call abilityDelegator.getAppContext') + var context = abilityDelegator.getAppContext() + console.info('getAppContext : ' + JSON.stringify(context)) + console.info('OpenHarmonyTestRunner onRun end') + } +}; \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 00000000..0f1243c9 --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import SensorMockTest from './Sensormock.test' + +export default function testsuite() { + SensorMockTest() +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets new file mode 100644 index 00000000..fc510caf --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/ets/test/Sensormock.test.ets @@ -0,0 +1,188 @@ +// @ts-nocheck +import { describe, it, expect, MockKit, when } from '@ohos/hypium' +import sensor from '@ohos.sensor'; + +export default function SensorMockTest() { + describe('sensorTest', function () { + it('sensorTest_on', 0, function () { + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.on); + + function NeedData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); + //从回调中拿到预置的数据 + newObj.on(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) { + console.log("mockSensor - on: " + JSON.stringify(data)); + }); + }); + + it('sensorTest_on_2', 0, function () { + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.on); + + function NeedData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); + //从回调中拿到预置的数据,并传入轮询周期时间 + newObj.on(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) { + console.log("mockSensor - on: " + JSON.stringify(data)); + }, { + interval: 3000000000 + }); + }); + + it('sensorTest_on_3', 0, function () { + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.on); + + function NeedData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); //模拟的数据 + let result = newObj.on(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER); + //从返回值中拿到预置的数据 + console.log("mockSensor - on: " + JSON.stringify(result)); + }); + + it('sensorTest_once', 0, function () { + + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.once); + + function NeedData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); //模拟的数据 + newObj.once(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) { + //从回调中拿到预置的数据 + console.log("mockSensor - once: " + JSON.stringify(data)); + }); + }); + + + it('sensorTest_off', 0, function () { + + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.off); + + function NeedData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER).afterReturn(new NeedData(1, 2, 3)); //模拟的数据 + newObj.off(newObj.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function (data) { + console.log("mockSensor - off: " + JSON.stringify(data)); //从回调中拿到预置的数据 + }); + }); + + + it('sensorTest_transformCoordinateSystem', 0, function () { + + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.transformCoordinateSystem); + + function SuccessData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)('transformCoordinateSystem').afterReturn(new SuccessData(1, 2, 3)); //模拟的数据 + newObj.transformCoordinateSystem('transformCoordinateSystem', function (data) { + //从回调中拿到预置的数据 + console.log("mockSensor - transformCoordinateSystem: " + JSON.stringify(data)); + }); + }); + + + it('sensorTest_transformCoordinateSystem_async', 0, async function () { + + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.transformCoordinateSystem); + + //模拟的数据 + when(mockedOnFunc)('transformCoordinateSystem').afterReturn(new Promise((data, err) => { + if (true) { + data('data you need'); + } else { + err('some error'); + } + })); + + //从返回值中拿到预置的数据promise + newObj.transformCoordinateSystem('transformCoordinateSystem').then((data)=>{ + console.info("mockSensor - Operation successed :" + data); + }).catch((err) => { + console.info("mockSensor - Operation failed :" + err); + }); + }); + + + it('sensorTest_getDirection', 0, function () { + + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.transformCoordinateSystem); + + function SuccessData(x, y, z) { + this.x = x + this.y = y + this.z = z + } + + when(mockedOnFunc)('getDirection').afterReturn(new SuccessData(1, 2, 3)); //模拟的数据 + newObj.transformCoordinateSystem('getDirection', function (data) { + //从回调中拿到预置的数据 + console.log("mockSensor - getDirection: " + JSON.stringify(data)); + }); + }); + + + it('sensorTest_getDirection_async', 0, async function () { + + let mocker = new MockKit(); + let newObj = mocker.mockObject(sensor); + let mockedOnFunc = mocker.mockFunc(newObj, newObj.getDirection); + + //模拟的数据 + when(mockedOnFunc)('getDirection').afterReturn(new Promise((data, err) => { + if (true) { + data('data you need'); + } else { + err('some error'); + } + })); + + //从返回值中拿到预置的数据promise + newObj.getDirection('getDirection').then((data)=>{ + console.info("mockSensor - Operation successed :" + data); + }).catch((err) => { + console.info("mockSensor - Operation failed :" + err); + }); + }); + }); +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 00000000..a0901cfc --- /dev/null +++ b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "description_TestAbility", + "value": "eTS_Empty Ability" + }, + { + "name": "entry_TestAbility", + "value": "entry_TestAbility" + } + ] +} \ No newline at end of file diff --git a/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/media/icon.png b/Ability/Sensormock/demo/SensorSimulateDemo/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 +
A unit test framework for OpenHarmonyOS application
+ +## 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.0" +} +``` +注: +hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导: +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 | assertEqual | 检验actualvalue是否等于expectvalue[0] | +| 4 | assertFail | 抛出一个错误 | +| 5 | assertFalse | 检验actualvalue是否是false | +| 6 | assertTrue | 检验actualvalue是否是true | +| 7 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 | +| 8 | assertLarger | 检验actualvalue是否大于expectvalue | +| 9 | assertLess | 检验actualvalue是否小于expectvalue | +| 10 | assertNull | 检验actualvalue是否是null | +| 11 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue | +| 12 | assertUndefined | 检验actualvalue是否是undefined | + + 示例代码: + +```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 | hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 | + + 示例代码: + +```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) + }) + }) +} +``` +- 专项能力 +用例筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。 + +| Key | 含义说明 | Value取值范围 | +| ---- | ------------------------------------------------------- | ------------------------------------------------------------ | +| level | 用例级别 | "0","1","2","3","4" | +| size | 用例粒度 | "small","medium","large" | +| testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience" | + + 示例代码 + +```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') + }) + }) +} +``` + + +## 约束 +*** + 本模块首批接口从OpenHarmony SDK API version 8开始支持。 + +## Hypium开放能力隐私声明 + +- 我们如何收集和使用您的个人信息 + 您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。 +- SDK处理的个人信息 + 不涉及。 +- SDK集成第三方服务声明 + 不涉及。 +- SDK数据安全保护 + 不涉及。 +- SDK版本更新声明 + 为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。 + + diff --git a/Ability/Sensormock/hypium/index.d.ts b/Ability/Sensormock/hypium/index.d.ts new file mode 100644 index 00000000..0be3926c --- /dev/null +++ b/Ability/Sensormock/hypium/index.d.ts @@ -0,0 +1,122 @@ +/* + * 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 +} + +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): 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 hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void +} \ No newline at end of file diff --git a/Ability/Sensormock/hypium/index.ets b/Ability/Sensormock/hypium/index.ets new file mode 100644 index 00000000..b778d290 --- /dev/null +++ b/Ability/Sensormock/hypium/index.ets @@ -0,0 +1,117 @@ +/* + * 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/core' +import {DEFAULT, TestType, Size, Level} from './src/Constant' +import DataDriver from './src/module/config/DataDriver' +import ExpectExtend from './src/module/assert/ExpectExtend' +import OhReport from './src/module/report/OhReport' +import SysTestKit from './src/module/kit/SysTestKit' +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/interface' +import {MockKit, when} from './src/module/mock/MockKit'; +import ArgumentMatchers from './src/module/mock/ArgumentMatchers'; + +function dryRun(core, testParameters, abilityDelegator) { + if (testParameters['dryRun'] === 'true') { + let testSuitesObj = {} + let suitesArray = [] + const suiteService = core.getDefaultService('suite') + for (const suiteItem of suiteService.rootSuite.childSuites) { + let itArray = [] + let suiteName = suiteItem['description'] + for (const itItem of suiteItem['specs']) { + itArray.push({'itName': itItem['description']}) + } + let obj = {} + obj[suiteName] = itArray + 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++) { + abilityDelegator.print(strJson.substring(count * maxLen, (count + 1) * maxLen)) + } + console.info('dryRun print success') + abilityDelegator.finishTest('dry run finished!!!', 0, () => { }) + return true + } + return false +} + +class Hypium { + static setData(data) { + const core = Core.getInstance() + const dataDriver = new DataDriver({data}) + core.addService('dataDriver', dataDriver) + } + + 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 + }) + 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 = configService.translateParams(abilityDelegatorArguments.parameters) + console.info('parameters:' + JSON.stringify(testParameters)) + configService.setConfig(testParameters) + testsuite() + if (dryRun(core, testParameters, abilityDelegator)) { + return + } + if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) { + globalThis.setupUiTestEnvironment().then(() => { + console.info('UiTestKit::after run uitest setup, start run testcases') + core.execute() + }).catch((error) => { + console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error) + core.execute() + }) + } else { + console.info('UiTestKit:: no need to setup uitest, start run testcases') + core.execute() + } + } +} + +export { + Hypium, + Core, + DEFAULT, + TestType, + Size, + Level, + DataDriver, + ExpectExtend, + OhReport, + SysTestKit, + describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, + MockKit, when, + ArgumentMatchers +} \ No newline at end of file diff --git a/Ability/Sensormock/hypium/index.js b/Ability/Sensormock/hypium/index.js new file mode 100644 index 00000000..9ca084f2 --- /dev/null +++ b/Ability/Sensormock/hypium/index.js @@ -0,0 +1,117 @@ +/* + * 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/core'; +import {DEFAULT, TestType, Size, Level} from './src/Constant'; +import DataDriver from './src/module/config/DataDriver'; +import ExpectExtend from './src/module/assert/ExpectExtend'; +import OhReport from './src/module/report/OhReport'; +import SysTestKit from './src/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/interface'; +import {MockKit, when} from './src/module/mock/MockKit'; +import ArgumentMatchers from './src/module/mock/ArgumentMatchers'; + +function dryRun(core, testParameters, abilityDelegator) { + if (testParameters['dryRun'] === 'true') { + let testSuitesObj = {}; + let suitesArray = []; + const suiteService = core.getDefaultService('suite'); + for (const suiteItem of suiteService.rootSuite.childSuites) { + let itArray = []; + let suiteName = suiteItem['description']; + for (const itItem of suiteItem['specs']) { + itArray.push({'itName': itItem['description']}); + } + let obj = {}; + obj[suiteName] = itArray; + 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++) { + abilityDelegator.print(strJson.substring(count * maxLen, (count + 1) * maxLen)); + } + console.info('dryRun print success'); + abilityDelegator.finishTest('dry run finished!!!', 0, () => { }); + return true; + } + return false; +} + +class Hypium { + static setData(data) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + 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 + }); + 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 = configService.translateParams(abilityDelegatorArguments.parameters); + console.info('parameters:' + JSON.stringify(testParameters)); + configService.setConfig(testParameters); + testsuite(); + if (dryRun(core, testParameters, abilityDelegator)) { + return; + } + if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) { + globalThis.setupUiTestEnvironment().then(() => { + console.info('UiTestKit::after run uitest setup, start run testcases'); + core.execute(); + }).catch((error) => { + console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error); + core.execute(); + }); + } else { + console.info('UiTestKit:: no need to setup uitest, start run testcases'); + core.execute(); + } + } +} + +export { + Hypium, + Core, + DEFAULT, + TestType, + Size, + Level, + DataDriver, + ExpectExtend, + OhReport, + SysTestKit, + describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, + MockKit, when, + ArgumentMatchers +}; \ No newline at end of file diff --git a/Ability/Sensormock/hypium/package.json b/Ability/Sensormock/hypium/package.json new file mode 100644 index 00000000..dbac7273 --- /dev/null +++ b/Ability/Sensormock/hypium/package.json @@ -0,0 +1,50 @@ +{ + "_from": "@ohos/hypium@1.0.1", + "_id": "@ohos/hypium@1.0.1", + "_inBundle": false, + "_integrity": "sha512-HaztFbgwYZCdVlayXirBlmJaNTXUO65qRgYnUmrhWGEzG7wFU2fyFbeXgQeYMVWFXgeezFOoHAPoS96TEE7TIQ==", + "_location": "/@ohos/hypium", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "@ohos/hypium@1.0.1", + "name": "@ohos/hypium", + "escapedName": "@ohos%2fhypium", + "scope": "@ohos", + "rawSpec": "1.0.1", + "saveSpec": null, + "fetchSpec": "1.0.1" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://repo.harmonyos.com/npm/@ohos/hypium/-/@ohos/hypium-1.0.1.tgz", + "_shasum": "788c286f5b18e41774c606d12fd93f625a4318ed", + "_spec": "@ohos/hypium@1.0.1", + "_where": "C:\\Users\\Administrator\\DevEcoStudioProjects\\SensorSimulateDemo", + "author": "", + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "A unit test framework for OpenHarmony application.", + "keywords": [ + "OpenHarmony", + "hypium" + ], + "license": "Apache-2.0", + "main": "index.js", + "name": "@ohos/hypium", + "ohos": { + "org": "ohos" + }, + "repository": { + "type": "git", + "url": "https://gitee.com/openharmony/arkXtest" + }, + "tags": [ + "OpenHarmony", + "hypium" + ], + "version": "1.0.1" +} diff --git a/Ability/Sensormock/hypium/src/Constant.js b/Ability/Sensormock/hypium/src/Constant.js new file mode 100644 index 00000000..f1829107 --- /dev/null +++ b/Ability/Sensormock/hypium/src/Constant.js @@ -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; +} diff --git a/Ability/Sensormock/hypium/src/core.js b/Ability/Sensormock/hypium/src/core.js new file mode 100644 index 00000000..0daf0426 --- /dev/null +++ b/Ability/Sensormock/hypium/src/core.js @@ -0,0 +1,150 @@ +/* + * 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); + } + } + } + + fireEvents(serviceName, eventName) { + const eventObj = this.events[serviceName]; + if (!eventObj) { + return; + } + for (const attr in eventObj) { + 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() { + const suiteService = this.getDefaultService('suite'); + suiteService.execute(); + } +} + +export default Core; diff --git a/Ability/Sensormock/hypium/src/event.js b/Ability/Sensormock/hypium/src/event.js new file mode 100644 index 00000000..28299c36 --- /dev/null +++ b/Ability/Sensormock/hypium/src/event.js @@ -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); + } + + specStart() { + for (let monitor in this.eventMonitors) { + this.eventMonitors[monitor]['specStart'](); + } + } + + specDone() { + for (const monitor in this.eventMonitors) { + this.eventMonitors[monitor]['specDone'](); + } + } +} + +class SuiteEvent { + constructor(attr) { + this.id = attr.id; + this.suiteContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + suiteStart() { + for (let monitor in this.eventMonitors) { + this.eventMonitors[monitor]['suiteStart'](); + } + } + + suiteDone() { + for (let monitor in this.eventMonitors) { + this.eventMonitors[monitor]['suiteDone'](); + } + } +} + +class TaskEvent { + constructor(attr) { + this.id = attr.id; + this.coreContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + taskStart() { + for (let monitor in this.eventMonitors) { + this.eventMonitors[monitor]['taskStart'](); + } + } + + taskDone() { + for (let monitor in this.eventMonitors) { + this.eventMonitors[monitor]['taskDone'](); + } + } + + incorrectFormat() { + for (let monitor in this.eventMonitors) { + this.eventMonitors[monitor]['incorrectFormat'](); + } + } +} + +export {SpecEvent, TaskEvent, SuiteEvent}; diff --git a/Ability/Sensormock/hypium/src/interface.js b/Ability/Sensormock/hypium/src/interface.js new file mode 100644 index 00000000..b4f145dc --- /dev/null +++ b/Ability/Sensormock/hypium/src/interface.js @@ -0,0 +1,65 @@ +/* + * 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) { + if (typeof globalThis !== 'undefined') { + return globalThis.describe(desc, func); + } + return core.describe(desc, func); +}; +const it = function (desc, filter, func) { + if (typeof globalThis !== 'undefined') { + return globalThis.it(desc, filter, func); + } + return core.it(desc, filter, func); +}; +const beforeEach = function (func) { + if (typeof globalThis !== 'undefined') { + return globalThis.beforeEach(func); + } + return core.beforeEach(func); +}; +const afterEach = function (func) { + if (typeof globalThis !== 'undefined') { + return globalThis.afterEach(func); + } + return core.afterEach(func); +}; +const beforeAll = function (func) { + if (typeof globalThis !== 'undefined') { + return globalThis.beforeAll(func); + } + return core.beforeAll(func); +}; +const afterAll = function (func) { + if (typeof globalThis !== 'undefined') { + return globalThis.afterAll(func); + } + return core.afterAll(func); +}; +const expect = function (actualValue) { + if (typeof globalThis !== 'undefined') { + return globalThis.expect(actualValue); + } + return core.expect(actualValue); +}; + +export { + describe, it, beforeAll, beforeEach, afterEach, afterAll, expect +}; diff --git a/Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js b/Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js new file mode 100644 index 00000000..9ea94a94 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/ExpectExtend.js @@ -0,0 +1,62 @@ +/* + * 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'; + +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; + } + + 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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertClose.js b/Ability/Sensormock/hypium/src/module/assert/assertClose.js new file mode 100644 index 00000000..63635bea --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertClose.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertContain.js b/Ability/Sensormock/hypium/src/module/assert/assertContain.js new file mode 100644 index 00000000..6b33e08b --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertContain.js @@ -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: 'except false, ' + actualValue + ' do not have ' + expect[0] + }; +} + +export default assertContain; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertFail.js b/Ability/Sensormock/hypium/src/module/assert/assertFail.js new file mode 100644 index 00000000..8ab4ac5c --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertFail.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertFalse.js b/Ability/Sensormock/hypium/src/module/assert/assertFalse.js new file mode 100644 index 00000000..5800fc7f --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertFalse.js @@ -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: 'except false, actualValue is ' + actualValue + }; +} + +export default assertFalse; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js b/Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js new file mode 100644 index 00000000..1e11b93f --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertInstanceOf.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertLarger.js b/Ability/Sensormock/hypium/src/module/assert/assertLarger.js new file mode 100644 index 00000000..a74f4a8c --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertLarger.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertLess.js b/Ability/Sensormock/hypium/src/module/assert/assertLess.js new file mode 100644 index 00000000..17e84b0a --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertLess.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertNull.js b/Ability/Sensormock/hypium/src/module/assert/assertNull.js new file mode 100644 index 00000000..53a7bad8 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertNull.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertThrowError.js b/Ability/Sensormock/hypium/src/module/assert/assertThrowError.js new file mode 100644 index 00000000..749cab0d --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertThrowError.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/assertUndefined.js b/Ability/Sensormock/hypium/src/module/assert/assertUndefined.js new file mode 100644 index 00000000..61f092d7 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/assertUndefined.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js b/Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js new file mode 100644 index 00000000..015ab19a --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/assert/isPromiseLike.js @@ -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; diff --git a/Ability/Sensormock/hypium/src/module/config/DataDriver.js b/Ability/Sensormock/hypium/src/module/config/DataDriver.js new file mode 100644 index 00000000..e521e455 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/config/DataDriver.js @@ -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) && describeValue === suiteDesc && (typeof describeValue === 'string') && describeValue.constructor === String) { + 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) && describeValue === suiteDesc && (typeof describeValue === 'string') && describeValue.constructor === String) { + 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) && describeValue === suiteDesc && (typeof describeValue === 'string') && describeValue.constructor === String) { + let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + return stress; + } +} + +export default DataDriver; diff --git a/Ability/Sensormock/hypium/src/module/config/Filter.js b/Ability/Sensormock/hypium/src/module/config/Filter.js new file mode 100644 index 00000000..356e5bc4 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/config/Filter.js @@ -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.includes(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}; diff --git a/Ability/Sensormock/hypium/src/module/config/configService.js b/Ability/Sensormock/hypium/src/module/config/configService.js new file mode 100644 index 00000000..682fd143 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/config/configService.js @@ -0,0 +1,269 @@ +/* + * 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'; + +class ConfigService { + constructor(attr) { + this.id = attr.id; + this.supportAsync = false; + this.random = false; + this.filterValid = []; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + isNormalInteger(str) { + const n = Math.floor(Number(str)); + return n !== Infinity && String(n) === String(str) && n >= 0; + } + + 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); + } + } + + if (params.dryRun !== undefined && params.dryRun !== 'true' && params.dryRun !== 'false') { + this.filterValid.push('dryRun:' + params.dryRun); + } + + let classes = params.class; + let nameRule = /^[A-Za-z]{1}[\w#,.]*$/; + if (classes !== undefined && classes !== '' && classes !== null) { + let classArray = classes.split(','); + for (let className of classArray) { + if (!className.match(nameRule)) { + this.filterValid.push('class:' + classes); + break; + } + } + } + let notClasses = params.notClass; + if (notClasses !== undefined && notClasses !== '' && notClasses !== null) { + let notClassArray = notClasses.split(','); + for (let notClassName of notClassArray) { + if (!notClassName.match(nameRule)) { + this.filterValid.push('notClass:' + notClasses); + break; + } + } + } + } + + 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.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) { + 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; + } + } + + 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; + } + + 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', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun' + ]); + 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', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun' + ]); + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key]; + } + } + return targetParams.trim(); + } + + execute() { + } +} + +export { + ConfigService +}; diff --git a/Ability/Sensormock/hypium/src/module/kit/SysTestKit.js b/Ability/Sensormock/hypium/src/module/kit/SysTestKit.js new file mode 100644 index 00000000..ded7e4bd --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/kit/SysTestKit.js @@ -0,0 +1,65 @@ +/* + * 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; + + 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.delegator.print(message).then(() => { + 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.delegator.print(message).then(() => { + console.info(tag + ' actionEnd print success'); + }); + } + + static async existKeyword(keyword, timeout) { + keyword = keyword || 'jsapp'; + 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; + } +} + +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; \ No newline at end of file diff --git a/Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js b/Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js new file mode 100644 index 00000000..6a9d7aac --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/mock/ArgumentMatchers.js @@ -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_STRING = ""; + ANY_BOOLEAN = ""; + ANY_NUMBER = ""; + ANY_OBJECT = ""; + ANY_FUNCTION = ""; + 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; \ No newline at end of file diff --git a/Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js b/Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js new file mode 100644 index 00000000..c6a866a6 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/mock/ExtendInterface.js @@ -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; \ No newline at end of file diff --git a/Ability/Sensormock/hypium/src/module/mock/MockKit.js b/Ability/Sensormock/hypium/src/module/mock/MockKit.js new file mode 100644 index 00000000..bcd7768c --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/mock/MockKit.js @@ -0,0 +1,281 @@ +/* + * 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]; + let matcher = new ArgumentMatchers(); + if (matcher.matcheStubKey(key)) { + key = matcher.matcheStubKey(key); + if (key) { + this.currentSetKey = key; + } + } + values.set(key, returnInfo); + console.info( + "set stub:" + f + ";" + "key:" + key + ",returnInfo:" + returnInfo + ); + this.stubs.set(f, values); + } + + getReturnInfo(f, params) { + let values = this.stubs.get(f); + console.info( + "getReruntInfo:" + f + ",values:" + values + ",params:" + params[0] + ); + + if (!values) { + return undefined; + } + let retrunKet = params[0]; + let stubSetKey = this.currentSetKey; + + if (this.currentSetKey && retrunKet) { + 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; + } + }); + + console.info("detail:" + values.get(retrunKet)); + 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); + console.log(records); + 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); + } + //1.0.3版本 新改动 + if (action) { + let result = action.apply(this, args); + if (args[1] && typeof args[1] == 'function') { + if (args[2]) { + let time = 0; + for (let o in args[2]) { + if (o == 'interval') { + time = args[2][o]; + } + } + setInterval(args[1](result), time / 1000000 > 0 ? time / 1000000 : 2000); + } else { + args[1](result); + } + } + return result; + } + ; + }; + + 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); + } + + /** + * 1.0.3版本 传感器,地理位置模拟新增接口 + * @param object + */ + 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 }; \ No newline at end of file diff --git a/Ability/Sensormock/hypium/src/module/mock/VerificationMode.js b/Ability/Sensormock/hypium/src/module/mock/VerificationMode.js new file mode 100644 index 00000000..8103a863 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/mock/VerificationMode.js @@ -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 "@ohos/hypium"; + +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; \ No newline at end of file diff --git a/Ability/Sensormock/hypium/src/module/report/OhReport.js b/Ability/Sensormock/hypium/src/module/report/OhReport.js new file mode 100644 index 00000000..0ee22a87 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/report/OhReport.js @@ -0,0 +1,126 @@ +/* + * 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 OhReport { + constructor(attr) { + this.delegator = attr.delegator; + 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() { + this.taskStartTime = new Date().getTime(); + } + + taskDone() { + this.taskDoneTime = new Date().getTime(); + this.duration = this.taskDoneTime - this.taskStartTime; + let summary = this.suiteService.getSummary(); + var message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure; + message += ', Error: ' + summary.error; + message += ', Pass: ' + summary.pass; + message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n'; + message += 'OHOS_REPORT_STATUS: consuming=' + this.duration + '\n'; + this.delegator.print(message).then(() => { + 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, () => { }); + } + } + + suiteStart() { + let suiteService = this.coreContext.getDefaultService('suite'); + var message = '\n' + 'OHOS_REPORT_SUM: ' + suiteService.getSummary().total; + message += '\n' + 'OHOS_REPORT_STATUS: class=' + suiteService.getCurrentRunningSuite().description + '\n'; + this.delegator.print(message).then(() => { + console.info(suiteService.getCurrentRunningSuite().description + ' print success'); + }); + } + + suiteDone() { + var message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: consuming=' + this.suiteService.currentRunningSuite.duration + '\n'; + this.delegator.print(message).then(() => { + console.info(suiteService.getCurrentRunningSuite().description + ' print success'); + }); + } + + specStart() { + let suiteService = this.coreContext.getDefaultService('suite'); + var message = '\n' + 'OHOS_REPORT_STATUS: class=' + suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + suiteService.getSummary().total; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n'; + this.delegator.print(message).then(() => { + console.info(this.specService.currentRunningSpec.description + ' start print success'); + }); + } + + specDone() { + var 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.suiteService.getSummary().total; + let emsg = ''; + if (this.specService.currentRunningSpec.error) { + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + this.specService.currentRunningSpec.error; + 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 => { + emsg = failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue || '')); + }); + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + emsg; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + emsg + '\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'; + this.delegator.print(message).then(() => { + console.info(this.specService.currentRunningSpec.description + ' end print success'); + }); + } +} + +export default OhReport; diff --git a/Ability/Sensormock/hypium/src/module/report/ReportExtend.js b/Ability/Sensormock/hypium/src/module/report/ReportExtend.js new file mode 100644 index 00000000..852fbcd5 --- /dev/null +++ b/Ability/Sensormock/hypium/src/module/report/ReportExtend.js @@ -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 = '\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}` : '/>'; + return xml; +} + +export default ReportExtend; diff --git a/Ability/Sensormock/hypium/src/service.js b/Ability/Sensormock/hypium/src/service.js new file mode 100644 index 00000000..dc74de3c --- /dev/null +++ b/Ability/Sensormock/hypium/src/service.js @@ -0,0 +1,702 @@ +/* + * 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 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; + coreContext.getDefaultService('config').setSupportAsync(true); + switch (funcLen) { + case 0: { + processedFunc = func; + break; + } + case 1: { + if (argNames[0] === 'data') { + processedFunc = function (paramItem) { + func(paramItem); + }; + } else { + processedFunc = function () { + return new Promise((resolve, reject) => { + function done() { + resolve(); + } + + let funcType = func(done); + if (funcType instanceof Promise) { + funcType.catch(err => {reject(err);}); + } + }); + }; + } + break; + } + default: { + processedFunc = function (paramItem) { + return new Promise((resolve, reject) => { + function done() { + resolve(); + } + + let funcType = func(done, paramItem); + if (funcType instanceof Promise) { + funcType.catch(err => {reject(err);}); + } + }); + }; + 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; + } + + describe(desc, func) { + if (this.coreContext.getDefaultService('config').filterSuite(desc)) { + console.info('filter suite :' + desc); + return; + } + const suite = new SuiteService.Suite({description: desc}); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined') { + let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc); + for (let i = 1; i < suiteStress; i++) { + this.currentRunningSuite.childSuites.push(suite); + } + } + const currentSuiteCache = this.currentRunningSuite; + this.currentRunningSuite.childSuites.push(suite); + this.currentRunningSuite = suite; + func.call(); + this.currentRunningSuite = currentSuiteCache; + } + + 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; + } + + getSummary() { + let total = 0; + let error = 0; + let failure = 0; + let pass = 0; + let rootSuite = this.coreContext.getDefaultService('suite').rootSuite; + if (rootSuite && rootSuite.childSuites) { + for (let i = 0; i < rootSuite.childSuites.length; i++) { + let testsuite = rootSuite.childSuites[i]; + let specs = testsuite['specs']; + for (let j = 0; j < specs.length; j++) { + total++; + let testcase = specs[j]; + if (testcase.error) { + error++; + } else if (testcase.result.failExpects.length > 0) { + failure++; + } else if (testcase.result.pass === true) { + pass++; + } + } + } + } + return {total: total, failure: failure, error: error, pass: pass}; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + execute() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + this.coreContext.fireEvents('task', 'incorrectFormat'); + return; + } + this.coreContext.fireEvents('task', 'taskStart'); + if (this.coreContext.getDefaultService('config').isSupportAsync()) { + let asyncExecute = async () => { + await this.rootSuite.asyncRun(this.coreContext); + }; + asyncExecute().then(() => { + this.coreContext.fireEvents('task', 'taskDone'); + }); + } else { + 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; + } + + run(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteStart', this); + } + let startTime = new Date().getTime(); + this.runHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return secureRandomNumber() > 0.5 ? -1 : 1; + }); + } + this.specs.forEach(spec => { + this.runHookFunc('beforeEach'); + spec.run(coreContext); + this.runHookFunc('afterEach'); + }); + } + if (this.childSuites.length > 0) { + this.childSuites.forEach(childSuite => { + childSuite.run(coreContext); + suiteService.setCurrentRunningSuite(childSuite); + }); + } + this.runHookFunc('afterAll'); + let endTime = new Date().getTime(); + this.duration = endTime - startTime; + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteDone'); + } + } + + asyncRun(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + return new Promise(async resolve => { + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteStart', this); + } + let startTime = new Date().getTime(); + await this.runAsyncHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return secureRandomNumber() > 0.5 ? -1 : 1; + }); + } + for (let i = 0; i < this.specs.length; i++) { + 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++) { + suiteService.setCurrentRunningSuite(this.childSuites[i]); + await this.childSuites[i].asyncRun(coreContext); + } + } + + await this.runAsyncHookFunc('afterAll'); + let endTime = new Date().getTime(); + this.duration = endTime - startTime; + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteDone'); + } + resolve(); + }); + } + + 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; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + setCurrentRunningSpec(spec) { + this.currentRunningSpec = spec; + } + + 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') { + let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc); + for (let i = 1; i < specStress; i++) { + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + 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; + } + + setResult() { + if (this.result.failExpects.length > 0) { + this.result.pass = false; + } 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); + let startTime = new Date().getTime(); + 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(); + } catch (e) { + this.error = e; + } + let endTime = new Date().getTime(); + this.duration = endTime - startTime; + coreContext.fireEvents('spec', 'specDone', this); + } + + asyncRun(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + const config = coreContext.getDefaultService('config'); + const timeout = + (config.timeout === undefined ? 5000 : config.timeout); + return new Promise(async resolve => { + coreContext.fireEvents('spec', 'specStart', this); + let startTime = new Date().getTime(); + + function timeoutPromise() { + return new Promise(function (resolve, reject) { + setTimeout(() => reject(new Error('execute timeout ' + timeout + 'ms')), timeout); + }); + } + + try { + let dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + const p = Promise.race([this.fn(), timeoutPromise()]); + await p.then(() => { + this.setResult(); + }); + } 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) { + const p = Promise.race([this.fn(), timeoutPromise()]); + await p.then(() => { + this.setResult(); + }); + } else if (specParams.length === 0) { + const p = Promise.race([this.fn(suiteParams), timeoutPromise()]); + await p.then(() => { + this.setResult(); + }); + } else { + for (const paramItem of specParams) { + const p = Promise.race([this.fn(Object.assign({}, paramItem, suiteParams)), timeoutPromise()]); + await p.then(() => { + this.setResult(); + }); + } + } + } + } catch (e) { + this.error = e; + } + let endTime = new Date().getTime(); + this.duration = endTime - startTime; + coreContext.fireEvents('spec', 'specDone', this); + resolve(); + }); + } + + filterCheck(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + return true; + } + + addExpectationResult(expectResult) { + if (expectResult.pass) { + this.result.passExpects.push(expectResult); + } else { + this.result.failExpects.push(expectResult); + } + } +}; + +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 + }; + }, + assertEqual: function (actualValue, args) { + return { + pass: (actualValue) === args[0], + expectValue: 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 = {}; + const specService = _this.coreContext.getDefaultService('spec'); + const currentRunningSpec = specService.getCurrentRunningSpec(); + for (const matcherName in this.matchers) { + if (Object.prototype.hasOwnProperty.call(this.matchers, matcherName)) { + wrappedMatchers[matcherName] = function () { + const result = _this.matchers[matcherName](actualValue, arguments); + result.actualValue = actualValue; + result.checkFunc = matcherName; + 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() { + this.sleep(50); + this.taskStartTime = new Date().getTime(); + console.info('[start] start run suites'); + } + + suiteStart() { + this.sleep(50); + console.info('[suite start]' + this.suiteService.getCurrentRunningSuite().description); + } + + specStart() { + this.sleep(50); + console.info('start running case \'' + this.specService.currentRunningSpec.description + '\''); + this.index = this.index + 1; + } + + specDone() { + this.sleep(50); + let msg = ''; + let spec = this.specService.currentRunningSpec; + 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() { + this.sleep(50); + let suite = this.suiteService.currentRunningSuite; + console.info('[suite end]' + ' consuming ' + suite.duration + 'ms'); + } + + taskDone() { + this.sleep(50); + let msg = ''; + this.taskDoneTime = new Date().getTime(); + this.duration = this.taskDoneTime - this.taskStartTime; + let summary = this.suiteService.getSummary(); + msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error; + msg += ',pass ' + summary.pass + '; consuming ' + this.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 +}; -- Gitee