From 4629732b243a5775fa7af8cc269962e70608920f Mon Sep 17 00:00:00 2001 From: miaodi <15035956535@163.com> Date: Wed, 12 Mar 2025 17:02:10 +0800 Subject: [PATCH 1/2] addlog Signed-off-by: miaodi <15035956535@163.com> --- .../src/main/ets/MainAbility/MainAbility.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/product/phone/src/main/ets/MainAbility/MainAbility.ts b/product/phone/src/main/ets/MainAbility/MainAbility.ts index 67501c1..a92c2d5 100644 --- a/product/phone/src/main/ets/MainAbility/MainAbility.ts +++ b/product/phone/src/main/ets/MainAbility/MainAbility.ts @@ -15,30 +15,31 @@ import Ability from '@ohos.application.Ability' import Notification from '@ohos.notification'; +import { LogUtils } from '@ohos/common/src/main/ets/utils/LogUtils' export default class MainAbility extends Ability { onCreate(want, launchParam) { - console.log("[Demo] MainAbility onCreate") + LogUtils.log("[Demo] MainAbility onCreate") globalThis.abilityWant = want; globalThis.abilityContext = this.context; } onDestroy() { Notification.cancelAll() - console.log("[Demo] MainAbility onDestroy") + LogUtils.log("[Demo] MainAbility onDestroy") } onWindowStageCreate(windowStage) { // Main window is created, set main page for this ability - console.log("[Demo] MainAbility onWindowStageCreate") + LogUtils.log("[Demo] MainAbility onWindowStageCreate") this.context.requestPermissionsFromUser(['ohos.permission.MICROPHONE', 'ohos.permission.WRITE_MEDIA', 'ohos.permission.READ_MEDIA']).then(() => { Notification.requestEnableNotification().then(() => { windowStage.loadContent("pages/index", (err, data) => { if (err.code) { - console.error('Failed to load the content. Cause:' + JSON.stringify(err)); + LogUtils.error('Failed to load the content. Cause:' + JSON.stringify(err)); return; } - console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) + LogUtils.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) }); }) }) @@ -46,16 +47,16 @@ export default class MainAbility extends Ability { onWindowStageDestroy() { // Main window is destroyed, release UI related resources - console.log("[Demo] MainAbility onWindowStageDestroy") + LogUtils.log("[Demo] MainAbility onWindowStageDestroy") } onForeground() { // Ability has brought to foreground - console.log("[Demo] MainAbility onForeground") + LogUtils.log("[Demo] MainAbility onForeground") } onBackground() { // Ability has back to background - console.log("[Demo] MainAbility onBackground") + LogUtils.log("[Demo] MainAbility onBackground") } }; -- Gitee From 8794cbd1fd9276562935e854fb886148383b9c7a Mon Sep 17 00:00:00 2001 From: miaodi <15035956535@163.com> Date: Sat, 15 Mar 2025 19:24:27 +0800 Subject: [PATCH 2/2] version Signed-off-by: miaodi <15035956535@163.com> --- build-profile.json5 | 8 +- common/BuildProfile.ets | 17 + common/build-profile.json5 | 14 +- common/oh-package.json5 | 12 + common/package.json | 4 +- common/src/main/ets/utils/Util.ets | 22 +- feature/recorder/BuildProfile.ets | 17 + feature/recorder/oh-package-lock.json5 | 18 + feature/recorder/oh-package.json5 | 13 + .../oh_modules/@ohos/common/.gitignore | 3 + .../oh_modules/@ohos/common/BuildProfile.ets | 17 + .../@ohos/common/build-profile.json5 | 17 + .../oh_modules/@ohos/common/hvigorfile.js | 3 + .../oh_modules/@ohos/common/index.ets | 20 + .../oh_modules/@ohos/common/oh-package.json5 | 12 + .../oh_modules/@ohos/common/package.json | 16 + .../common/src/main/ets/utils/ConfigData.ets | 25 + .../common/src/main/ets/utils/LogUtil.ts | 44 + .../@ohos/common/src/main/ets/utils/Util.ets | 109 ++ .../@ohos/common/src/main/module.json5 | 11 + .../main/resources/base/element/color.json | 32 + .../main/resources/base/element/string.json | 56 + .../main/resources/base/media/bg_record.png | Bin 0 -> 3806 bytes .../src/main/resources/base/media/ic_back.svg | 10 + .../resources/base/media/ic_clock_add.svg | 8 + .../resources/base/media/ic_clock_enhance.svg | 10 + .../resources/base/media/ic_clock_mark.svg | 8 + .../resources/base/media/ic_clock_play.svg | 7 + .../resources/base/media/ic_clock_record.svg | 7 + .../resources/base/media/ic_clock_stop.svg | 7 + .../resources/base/media/ic_clock_suspend.svg | 8 + .../resources/base/media/ic_record_play.svg | 8 + .../resources/base/media/ic_record_search.svg | 8 + .../resources/base/media/ic_record_stop.svg | 9 + .../main/resources/base/media/public_more.svg | 13 + .../main/ets/controller/AudioController.ets | 155 +-- .../main/ets/controller/MediaController.ets | 68 +- .../main/ets/controller/RecordController.ets | 182 ++-- .../main/ets/controller/StateController.ets | 10 +- .../src/main/ets/model/RecordData.ets | 29 +- hvigor/hvigor-config.json5 | 11 + oh-package-lock.json5 | 20 + oh-package.json5 | 20 + .../oh_modules/@ohos/hypium/CHANGELOG.md | 50 + .../oh_modules/@ohos/hypium/LICENSE | 177 ++++ .../oh_modules/@ohos/hypium/README.md | 219 ++++ .../oh_modules/@ohos/hypium/index.d.ts | 136 +++ .../oh_modules/@ohos/hypium/index.ets | 88 ++ .../oh_modules/@ohos/hypium/index.js | 81 ++ .../oh_modules/@ohos/hypium/oh-package.json5 | 11 + .../@ohos/hypium/src/main/Constant.js | 49 + .../oh_modules/@ohos/hypium/src/main/core.js | 159 +++ .../oh_modules/@ohos/hypium/src/main/event.js | 94 ++ .../@ohos/hypium/src/main/interface.js | 44 + .../src/main/module/assert/ExpectExtend.js | 85 ++ .../src/main/module/assert/assertClose.js | 41 + .../src/main/module/assert/assertContain.js | 35 + .../src/main/module/assert/assertFail.js | 23 + .../src/main/module/assert/assertFalse.js | 23 + .../main/module/assert/assertInstanceOf.js | 29 + .../src/main/module/assert/assertLarger.js | 23 + .../main/module/assert/assertLargerOrEqual.js | 23 + .../src/main/module/assert/assertLess.js | 23 + .../main/module/assert/assertLessOrEqual.js | 23 + .../src/main/module/assert/assertNaN.js | 23 + .../main/module/assert/assertNegUnlimited.js | 23 + .../src/main/module/assert/assertNull.js | 23 + .../main/module/assert/assertPosUnlimited.js | 23 + .../module/assert/assertPromiseIsPending.js | 42 + .../module/assert/assertPromiseIsRejected.js | 40 + .../assert/assertPromiseIsRejectedWith.js | 57 ++ .../assertPromiseIsRejectedWithError.js | 78 ++ .../module/assert/assertPromiseIsResolved.js | 45 + .../assert/assertPromiseIsResolvedWith.js | 59 ++ .../main/module/assert/assertThrowError.js | 44 + .../src/main/module/assert/assertUndefined.js | 23 + .../module/assert/deepEquals/DeepTypeUtils.js | 138 +++ .../assert/deepEquals/assertDeepEquals.js | 315 ++++++ .../src/main/module/assert/isPromiseLike.js | 32 + .../src/main/module/config/DataDriver.js | 116 +++ .../hypium/src/main/module/config/Filter.js | 81 ++ .../src/main/module/config/configService.js | 293 ++++++ .../main/module/coverage/coverageCollect.js | 31 + .../hypium/src/main/module/kit/SysTestKit.js | 88 ++ .../src/main/module/mock/ArgumentMatchers.js | 122 +++ .../src/main/module/mock/ExtendInterface.js | 57 ++ .../hypium/src/main/module/mock/MockKit.js | 256 +++++ .../src/main/module/mock/VerificationMode.js | 49 + .../hypium/src/main/module/report/OhReport.js | 152 +++ .../src/main/module/report/ReportExtend.js | 137 +++ .../@ohos/hypium/src/main/service.js | 966 ++++++++++++++++++ oh_modules/.ohpm/lock.json5 | 102 ++ .../oh_modules/@ohos/hypium/CHANGELOG.md | 50 + .../.ohpm/oh_modules/@ohos/hypium/LICENSE | 177 ++++ .../.ohpm/oh_modules/@ohos/hypium/README.md | 219 ++++ .../.ohpm/oh_modules/@ohos/hypium/index.d.ts | 136 +++ .../.ohpm/oh_modules/@ohos/hypium/index.ets | 88 ++ .../.ohpm/oh_modules/@ohos/hypium/index.js | 81 ++ .../oh_modules/@ohos/hypium/oh-package.json5 | 11 + .../@ohos/hypium/src/main/Constant.js | 49 + .../oh_modules/@ohos/hypium/src/main/core.js | 159 +++ .../oh_modules/@ohos/hypium/src/main/event.js | 94 ++ .../@ohos/hypium/src/main/interface.js | 44 + .../src/main/module/assert/ExpectExtend.js | 85 ++ .../src/main/module/assert/assertClose.js | 41 + .../src/main/module/assert/assertContain.js | 35 + .../src/main/module/assert/assertFail.js | 23 + .../src/main/module/assert/assertFalse.js | 23 + .../main/module/assert/assertInstanceOf.js | 29 + .../src/main/module/assert/assertLarger.js | 23 + .../main/module/assert/assertLargerOrEqual.js | 23 + .../src/main/module/assert/assertLess.js | 23 + .../main/module/assert/assertLessOrEqual.js | 23 + .../src/main/module/assert/assertNaN.js | 23 + .../main/module/assert/assertNegUnlimited.js | 23 + .../src/main/module/assert/assertNull.js | 23 + .../main/module/assert/assertPosUnlimited.js | 23 + .../module/assert/assertPromiseIsPending.js | 42 + .../module/assert/assertPromiseIsRejected.js | 40 + .../assert/assertPromiseIsRejectedWith.js | 57 ++ .../assertPromiseIsRejectedWithError.js | 78 ++ .../module/assert/assertPromiseIsResolved.js | 45 + .../assert/assertPromiseIsResolvedWith.js | 59 ++ .../main/module/assert/assertThrowError.js | 44 + .../src/main/module/assert/assertUndefined.js | 23 + .../module/assert/deepEquals/DeepTypeUtils.js | 138 +++ .../assert/deepEquals/assertDeepEquals.js | 315 ++++++ .../src/main/module/assert/isPromiseLike.js | 32 + .../src/main/module/config/DataDriver.js | 116 +++ .../hypium/src/main/module/config/Filter.js | 81 ++ .../src/main/module/config/configService.js | 293 ++++++ .../main/module/coverage/coverageCollect.js | 31 + .../hypium/src/main/module/kit/SysTestKit.js | 88 ++ .../src/main/module/mock/ArgumentMatchers.js | 122 +++ .../src/main/module/mock/ExtendInterface.js | 57 ++ .../hypium/src/main/module/mock/MockKit.js | 256 +++++ .../src/main/module/mock/VerificationMode.js | 49 + .../hypium/src/main/module/report/OhReport.js | 152 +++ .../src/main/module/report/ReportExtend.js | 137 +++ .../@ohos/hypium/src/main/service.js | 966 ++++++++++++++++++ oh_modules/@ohos/hypium/CHANGELOG.md | 50 + oh_modules/@ohos/hypium/LICENSE | 177 ++++ oh_modules/@ohos/hypium/README.md | 219 ++++ oh_modules/@ohos/hypium/index.d.ts | 136 +++ oh_modules/@ohos/hypium/index.ets | 88 ++ oh_modules/@ohos/hypium/index.js | 81 ++ oh_modules/@ohos/hypium/oh-package.json5 | 11 + oh_modules/@ohos/hypium/src/main/Constant.js | 49 + oh_modules/@ohos/hypium/src/main/core.js | 159 +++ oh_modules/@ohos/hypium/src/main/event.js | 94 ++ oh_modules/@ohos/hypium/src/main/interface.js | 44 + .../src/main/module/assert/ExpectExtend.js | 85 ++ .../src/main/module/assert/assertClose.js | 41 + .../src/main/module/assert/assertContain.js | 35 + .../src/main/module/assert/assertFail.js | 23 + .../src/main/module/assert/assertFalse.js | 23 + .../main/module/assert/assertInstanceOf.js | 29 + .../src/main/module/assert/assertLarger.js | 23 + .../main/module/assert/assertLargerOrEqual.js | 23 + .../src/main/module/assert/assertLess.js | 23 + .../main/module/assert/assertLessOrEqual.js | 23 + .../src/main/module/assert/assertNaN.js | 23 + .../main/module/assert/assertNegUnlimited.js | 23 + .../src/main/module/assert/assertNull.js | 23 + .../main/module/assert/assertPosUnlimited.js | 23 + .../module/assert/assertPromiseIsPending.js | 42 + .../module/assert/assertPromiseIsRejected.js | 40 + .../assert/assertPromiseIsRejectedWith.js | 57 ++ .../assertPromiseIsRejectedWithError.js | 78 ++ .../module/assert/assertPromiseIsResolved.js | 45 + .../assert/assertPromiseIsResolvedWith.js | 59 ++ .../main/module/assert/assertThrowError.js | 44 + .../src/main/module/assert/assertUndefined.js | 23 + .../module/assert/deepEquals/DeepTypeUtils.js | 138 +++ .../assert/deepEquals/assertDeepEquals.js | 315 ++++++ .../src/main/module/assert/isPromiseLike.js | 32 + .../src/main/module/config/DataDriver.js | 116 +++ .../hypium/src/main/module/config/Filter.js | 81 ++ .../src/main/module/config/configService.js | 293 ++++++ .../main/module/coverage/coverageCollect.js | 31 + .../hypium/src/main/module/kit/SysTestKit.js | 88 ++ .../src/main/module/mock/ArgumentMatchers.js | 122 +++ .../src/main/module/mock/ExtendInterface.js | 57 ++ .../hypium/src/main/module/mock/MockKit.js | 256 +++++ .../src/main/module/mock/VerificationMode.js | 49 + .../hypium/src/main/module/report/OhReport.js | 152 +++ .../src/main/module/report/ReportExtend.js | 137 +++ oh_modules/@ohos/hypium/src/main/service.js | 966 ++++++++++++++++++ product/phone/oh-package-lock.json5 | 25 + product/phone/oh-package.json5 | 12 + .../phone/oh_modules/@ohos/common/.gitignore | 3 + .../oh_modules/@ohos/common/BuildProfile.ets | 17 + .../@ohos/common/build-profile.json5 | 17 + .../oh_modules/@ohos/common/hvigorfile.js | 3 + .../phone/oh_modules/@ohos/common/index.ets | 20 + .../oh_modules/@ohos/common/oh-package.json5 | 12 + .../oh_modules/@ohos/common/package.json | 16 + .../common/src/main/ets/utils/ConfigData.ets | 25 + .../common/src/main/ets/utils/LogUtil.ts | 44 + .../@ohos/common/src/main/ets/utils/Util.ets | 109 ++ .../@ohos/common/src/main/module.json5 | 11 + .../main/resources/base/element/color.json | 32 + .../main/resources/base/element/string.json | 56 + .../main/resources/base/media/bg_record.png | Bin 0 -> 3806 bytes .../src/main/resources/base/media/ic_back.svg | 10 + .../resources/base/media/ic_clock_add.svg | 8 + .../resources/base/media/ic_clock_enhance.svg | 10 + .../resources/base/media/ic_clock_mark.svg | 8 + .../resources/base/media/ic_clock_play.svg | 7 + .../resources/base/media/ic_clock_record.svg | 7 + .../resources/base/media/ic_clock_stop.svg | 7 + .../resources/base/media/ic_clock_suspend.svg | 8 + .../resources/base/media/ic_record_play.svg | 8 + .../resources/base/media/ic_record_search.svg | 8 + .../resources/base/media/ic_record_stop.svg | 9 + .../main/resources/base/media/public_more.svg | 13 + .../oh_modules/@ohos/recorder/.gitignore | 3 + .../@ohos/recorder/BuildProfile.ets | 17 + .../@ohos/recorder/build-profile.json5 | 5 + .../oh_modules/@ohos/recorder/hvigorfile.js | 3 + .../phone/oh_modules/@ohos/recorder/index.ets | 24 + .../@ohos/recorder/oh-package-lock.json5 | 18 + .../@ohos/recorder/oh-package.json5 | 13 + .../oh_modules/@ohos/common/.gitignore | 3 + .../oh_modules/@ohos/common/BuildProfile.ets | 17 + .../@ohos/common/build-profile.json5 | 17 + .../oh_modules/@ohos/common/hvigorfile.js | 3 + .../oh_modules/@ohos/common/index.ets | 20 + .../oh_modules/@ohos/common/oh-package.json5 | 12 + .../oh_modules/@ohos/common/package.json | 16 + .../common/src/main/ets/utils/ConfigData.ets | 25 + .../common/src/main/ets/utils/LogUtil.ts | 44 + .../@ohos/common/src/main/ets/utils/Util.ets | 109 ++ .../@ohos/common/src/main/module.json5 | 11 + .../main/resources/base/element/color.json | 32 + .../main/resources/base/element/string.json | 56 + .../main/resources/base/media/bg_record.png | Bin 0 -> 3806 bytes .../src/main/resources/base/media/ic_back.svg | 10 + .../resources/base/media/ic_clock_add.svg | 8 + .../resources/base/media/ic_clock_enhance.svg | 10 + .../resources/base/media/ic_clock_mark.svg | 8 + .../resources/base/media/ic_clock_play.svg | 7 + .../resources/base/media/ic_clock_record.svg | 7 + .../resources/base/media/ic_clock_stop.svg | 7 + .../resources/base/media/ic_clock_suspend.svg | 8 + .../resources/base/media/ic_record_play.svg | 8 + .../resources/base/media/ic_record_search.svg | 8 + .../resources/base/media/ic_record_stop.svg | 9 + .../main/resources/base/media/public_more.svg | 13 + .../oh_modules/@ohos/recorder/package.json | 16 + .../main/ets/controller/AudioController.ets | 202 ++++ .../main/ets/controller/MediaController.ets | 56 + .../main/ets/controller/RecordController.ets | 189 ++++ .../main/ets/controller/StateController.ets | 66 ++ .../src/main/ets/model/RecordData.ets | 43 + .../@ohos/recorder/src/main/module.json5 | 11 + .../main/resources/base/element/string.json | 8 + .../main/ets/Application/MyAbilityStage.ts | 2 +- .../src/main/ets/MainAbility/MainAbility.ts | 27 +- .../src/main/ets/pages/RecordingPage.ets | 43 +- product/phone/src/main/ets/pages/index.ets | 63 +- product/phone/src/main/module.json5 | 30 +- product/tablet/oh-package-lock.json5 | 25 + product/tablet/oh-package.json5 | 12 + .../tablet/oh_modules/@ohos/common/.gitignore | 3 + .../oh_modules/@ohos/common/BuildProfile.ets | 17 + .../@ohos/common/build-profile.json5 | 17 + .../oh_modules/@ohos/common/hvigorfile.js | 3 + .../tablet/oh_modules/@ohos/common/index.ets | 20 + .../oh_modules/@ohos/common/oh-package.json5 | 12 + .../oh_modules/@ohos/common/package.json | 16 + .../common/src/main/ets/utils/ConfigData.ets | 25 + .../common/src/main/ets/utils/LogUtil.ts | 44 + .../@ohos/common/src/main/ets/utils/Util.ets | 109 ++ .../@ohos/common/src/main/module.json5 | 11 + .../main/resources/base/element/color.json | 32 + .../main/resources/base/element/string.json | 56 + .../main/resources/base/media/bg_record.png | Bin 0 -> 3806 bytes .../src/main/resources/base/media/ic_back.svg | 10 + .../resources/base/media/ic_clock_add.svg | 8 + .../resources/base/media/ic_clock_enhance.svg | 10 + .../resources/base/media/ic_clock_mark.svg | 8 + .../resources/base/media/ic_clock_play.svg | 7 + .../resources/base/media/ic_clock_record.svg | 7 + .../resources/base/media/ic_clock_stop.svg | 7 + .../resources/base/media/ic_clock_suspend.svg | 8 + .../resources/base/media/ic_record_play.svg | 8 + .../resources/base/media/ic_record_search.svg | 8 + .../resources/base/media/ic_record_stop.svg | 9 + .../main/resources/base/media/public_more.svg | 13 + .../oh_modules/@ohos/recorder/.gitignore | 3 + .../@ohos/recorder/BuildProfile.ets | 17 + .../@ohos/recorder/build-profile.json5 | 5 + .../oh_modules/@ohos/recorder/hvigorfile.js | 3 + .../oh_modules/@ohos/recorder/index.ets | 24 + .../@ohos/recorder/oh-package-lock.json5 | 18 + .../@ohos/recorder/oh-package.json5 | 13 + .../oh_modules/@ohos/common/.gitignore | 3 + .../oh_modules/@ohos/common/BuildProfile.ets | 17 + .../@ohos/common/build-profile.json5 | 17 + .../oh_modules/@ohos/common/hvigorfile.js | 3 + .../oh_modules/@ohos/common/index.ets | 20 + .../oh_modules/@ohos/common/oh-package.json5 | 12 + .../oh_modules/@ohos/common/package.json | 16 + .../common/src/main/ets/utils/ConfigData.ets | 25 + .../common/src/main/ets/utils/LogUtil.ts | 44 + .../@ohos/common/src/main/ets/utils/Util.ets | 109 ++ .../@ohos/common/src/main/module.json5 | 11 + .../main/resources/base/element/color.json | 32 + .../main/resources/base/element/string.json | 56 + .../main/resources/base/media/bg_record.png | Bin 0 -> 3806 bytes .../src/main/resources/base/media/ic_back.svg | 10 + .../resources/base/media/ic_clock_add.svg | 8 + .../resources/base/media/ic_clock_enhance.svg | 10 + .../resources/base/media/ic_clock_mark.svg | 8 + .../resources/base/media/ic_clock_play.svg | 7 + .../resources/base/media/ic_clock_record.svg | 7 + .../resources/base/media/ic_clock_stop.svg | 7 + .../resources/base/media/ic_clock_suspend.svg | 8 + .../resources/base/media/ic_record_play.svg | 8 + .../resources/base/media/ic_record_search.svg | 8 + .../resources/base/media/ic_record_stop.svg | 9 + .../main/resources/base/media/public_more.svg | 13 + .../oh_modules/@ohos/recorder/package.json | 16 + .../main/ets/controller/AudioController.ets | 202 ++++ .../main/ets/controller/MediaController.ets | 56 + .../main/ets/controller/RecordController.ets | 189 ++++ .../main/ets/controller/StateController.ets | 66 ++ .../src/main/ets/model/RecordData.ets | 43 + .../@ohos/recorder/src/main/module.json5 | 11 + .../main/resources/base/element/string.json | 8 + .../main/ets/Application/MyAbilityStage.ts | 2 +- .../src/main/ets/MainAbility/MainAbility.ts | 14 +- .../src/main/ets/pages/RecordingPage.ets | 36 +- .../tablet/src/main/ets/pages/recordList.ets | 79 +- product/tablet/src/main/module.json5 | 22 +- 336 files changed, 18503 insertions(+), 546 deletions(-) create mode 100644 common/BuildProfile.ets create mode 100644 common/oh-package.json5 create mode 100644 feature/recorder/BuildProfile.ets create mode 100644 feature/recorder/oh-package-lock.json5 create mode 100644 feature/recorder/oh-package.json5 create mode 100644 feature/recorder/oh_modules/@ohos/common/.gitignore create mode 100644 feature/recorder/oh_modules/@ohos/common/BuildProfile.ets create mode 100644 feature/recorder/oh_modules/@ohos/common/build-profile.json5 create mode 100644 feature/recorder/oh_modules/@ohos/common/hvigorfile.js create mode 100644 feature/recorder/oh_modules/@ohos/common/index.ets create mode 100644 feature/recorder/oh_modules/@ohos/common/oh-package.json5 create mode 100644 feature/recorder/oh_modules/@ohos/common/package.json create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/module.json5 create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg create mode 100644 feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg create mode 100644 hvigor/hvigor-config.json5 create mode 100644 oh-package-lock.json5 create mode 100644 oh-package.json5 create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/CHANGELOG.md create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/LICENSE create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/README.md create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.d.ts create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.ets create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/oh-package.json5 create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/Constant.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/core.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/event.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/interface.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/Filter.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/configService.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js create mode 100644 oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/service.js create mode 100644 oh_modules/.ohpm/lock.json5 create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/CHANGELOG.md create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/LICENSE create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/README.md create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/index.d.ts create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/index.ets create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/index.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/oh-package.json5 create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/Constant.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/core.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/event.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/interface.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/Filter.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/configService.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js create mode 100644 oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/service.js create mode 100644 oh_modules/@ohos/hypium/CHANGELOG.md create mode 100644 oh_modules/@ohos/hypium/LICENSE create mode 100644 oh_modules/@ohos/hypium/README.md create mode 100644 oh_modules/@ohos/hypium/index.d.ts create mode 100644 oh_modules/@ohos/hypium/index.ets create mode 100644 oh_modules/@ohos/hypium/index.js create mode 100644 oh_modules/@ohos/hypium/oh-package.json5 create mode 100644 oh_modules/@ohos/hypium/src/main/Constant.js create mode 100644 oh_modules/@ohos/hypium/src/main/core.js create mode 100644 oh_modules/@ohos/hypium/src/main/event.js create mode 100644 oh_modules/@ohos/hypium/src/main/interface.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/config/Filter.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/config/configService.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/report/OhReport.js create mode 100644 oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js create mode 100644 oh_modules/@ohos/hypium/src/main/service.js create mode 100644 product/phone/oh-package-lock.json5 create mode 100644 product/phone/oh-package.json5 create mode 100644 product/phone/oh_modules/@ohos/common/.gitignore create mode 100644 product/phone/oh_modules/@ohos/common/BuildProfile.ets create mode 100644 product/phone/oh_modules/@ohos/common/build-profile.json5 create mode 100644 product/phone/oh_modules/@ohos/common/hvigorfile.js create mode 100644 product/phone/oh_modules/@ohos/common/index.ets create mode 100644 product/phone/oh_modules/@ohos/common/oh-package.json5 create mode 100644 product/phone/oh_modules/@ohos/common/package.json create mode 100644 product/phone/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets create mode 100644 product/phone/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts create mode 100644 product/phone/oh_modules/@ohos/common/src/main/ets/utils/Util.ets create mode 100644 product/phone/oh_modules/@ohos/common/src/main/module.json5 create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/element/color.json create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/element/string.json create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg create mode 100644 product/phone/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/.gitignore create mode 100644 product/phone/oh_modules/@ohos/recorder/BuildProfile.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/build-profile.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/hvigorfile.js create mode 100644 product/phone/oh_modules/@ohos/recorder/index.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/oh-package-lock.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/oh-package.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg create mode 100644 product/phone/oh_modules/@ohos/recorder/package.json create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/module.json5 create mode 100644 product/phone/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json create mode 100644 product/tablet/oh-package-lock.json5 create mode 100644 product/tablet/oh-package.json5 create mode 100644 product/tablet/oh_modules/@ohos/common/.gitignore create mode 100644 product/tablet/oh_modules/@ohos/common/BuildProfile.ets create mode 100644 product/tablet/oh_modules/@ohos/common/build-profile.json5 create mode 100644 product/tablet/oh_modules/@ohos/common/hvigorfile.js create mode 100644 product/tablet/oh_modules/@ohos/common/index.ets create mode 100644 product/tablet/oh_modules/@ohos/common/oh-package.json5 create mode 100644 product/tablet/oh_modules/@ohos/common/package.json create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/ets/utils/Util.ets create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/module.json5 create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/color.json create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/string.json create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg create mode 100644 product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/.gitignore create mode 100644 product/tablet/oh_modules/@ohos/recorder/BuildProfile.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/build-profile.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/hvigorfile.js create mode 100644 product/tablet/oh_modules/@ohos/recorder/index.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh-package-lock.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh-package.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg create mode 100644 product/tablet/oh_modules/@ohos/recorder/package.json create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/module.json5 create mode 100644 product/tablet/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json diff --git a/build-profile.json5 b/build-profile.json5 index ec555ee..dc712a8 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -1,14 +1,14 @@ { "app": { "signingConfigs": [], - "compileSdkVersion": 9, - "compatibleSdkVersion": 9, "products": [ { + "compileSdkVersion": 11, + "compatibleSdkVersion": 11, "name": "default", - "signingConfig": "default", + "signingConfig": "default" } - ] + ], }, "modules": [ { diff --git a/common/BuildProfile.ets b/common/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/common/build-profile.json5 b/common/build-profile.json5 index 35dff6d..7374b5c 100644 --- a/common/build-profile.json5 +++ b/common/build-profile.json5 @@ -1,5 +1,17 @@ { "apiType": "stageMode", "buildOption": { - } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + } + } + } + }, + ] } diff --git a/common/oh-package.json5 b/common/oh-package.json5 new file mode 100644 index 0000000..3159c13 --- /dev/null +++ b/common/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "index.ets", + "version": "1.0.0", +} diff --git a/common/package.json b/common/package.json index 6845131..dfbf6f7 100644 --- a/common/package.json +++ b/common/package.json @@ -10,5 +10,7 @@ "main": "src/main/ets/components/MainPage/MainPage.ets", "repository": {}, "version": "1.0.0", - "dependencies": {} + "dependencies": { + "@ohos/hap": "^3.0.0" + } } diff --git a/common/src/main/ets/utils/Util.ets b/common/src/main/ets/utils/Util.ets index 2887d8f..d7ff070 100644 --- a/common/src/main/ets/utils/Util.ets +++ b/common/src/main/ets/utils/Util.ets @@ -28,12 +28,12 @@ export default class Util { let timeStr = ""; let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); if (hasHour || hour > 0) { - timeStr += this.addZero(hour) + ":"; + timeStr += Util.addZero(hour) + ":"; } let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); - timeStr += this.addZero(min) + ":"; + timeStr += Util.addZero(min) + ":"; let sec = Math.floor(timestamp % (60 * 1000) / 1000); - timeStr += this.addZero(sec); + timeStr += Util.addZero(sec); return timeStr; } @@ -49,15 +49,15 @@ export default class Util { let timeStr = ""; let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); if (hour > 0) { - timeStr += this.addZero(hour) + ":"; + timeStr += Util.addZero(hour) + ":"; } let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); - timeStr += this.addZero(min) + ":"; + timeStr += Util.addZero(min) + ":"; let sec = Math.floor(timestamp % (60 * 1000) / 1000); - timeStr += this.addZero(sec); + timeStr += Util.addZero(sec); if (hour < 1) { let mSec = Math.floor(timestamp % 1000 / 10); - timeStr += "." + this.addZero(mSec); + timeStr += "." + Util.addZero(mSec); } return timeStr; } @@ -69,7 +69,7 @@ export default class Util { */ static getDateFormat(date: number): string { let nowDate = new Date(date); - return nowDate.getFullYear() + "/" + this.addZero(nowDate.getMonth() + 1) + "/" + this.addZero(nowDate.getDate()); + return nowDate.getFullYear() + "/" + Util.addZero(nowDate.getMonth() + 1) + "/" + Util.addZero(nowDate.getDate()); } /** @@ -79,7 +79,7 @@ export default class Util { */ static getTimeFormat(date: number): string { let nowDate = new Date(date); - return this.addZero(nowDate.getHours()) + ":" + this.addZero(nowDate.getMinutes()) + ":" + this.addZero(nowDate.getSeconds()); + return Util.addZero(nowDate.getHours()) + ":" + Util.addZero(nowDate.getMinutes()) + ":" + Util.addZero(nowDate.getSeconds()); } /** @@ -87,7 +87,7 @@ export default class Util { */ static getDate(): string { let nowDate = new Date(); - return nowDate.getFullYear() + this.addZero(nowDate.getMonth() + 1) + this.addZero(nowDate.getDate()); + return nowDate.getFullYear() + Util.addZero(nowDate.getMonth() + 1) + Util.addZero(nowDate.getDate()); } /** @@ -95,7 +95,7 @@ export default class Util { */ static getTime(): string { let nowDate = new Date(); - return this.addZero(nowDate.getHours()) + this.addZero(nowDate.getMinutes()) + this.addZero(nowDate.getSeconds()); + return Util.addZero(nowDate.getHours()) + Util.addZero(nowDate.getMinutes()) + Util.addZero(nowDate.getSeconds()); } /** diff --git a/feature/recorder/BuildProfile.ets b/feature/recorder/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/feature/recorder/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/feature/recorder/oh-package-lock.json5 b/feature/recorder/oh-package-lock.json5 new file mode 100644 index 0000000..71fb2aa --- /dev/null +++ b/feature/recorder/oh-package-lock.json5 @@ -0,0 +1,18 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/common@../../common": "@ohos/common@../../common" + }, + "packages": { + "@ohos/common@../../common": { + "name": "@ohos/common", + "version": "1.0.0", + "resolved": "../../common", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/feature/recorder/oh-package.json5 b/feature/recorder/oh-package.json5 new file mode 100644 index 0000000..c395a28 --- /dev/null +++ b/feature/recorder/oh-package.json5 @@ -0,0 +1,13 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": { + "@ohos/common": "file:../../common" + }, + "name": "@ohos/recorder", + "description": "a npm package which contains arkUI2.0 page", + "main": "index.ets", + "version": "1.0.0", + "dynamicDependencies": {}, + "dependencies": {} +} diff --git a/feature/recorder/oh_modules/@ohos/common/.gitignore b/feature/recorder/oh_modules/@ohos/common/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/BuildProfile.ets b/feature/recorder/oh_modules/@ohos/common/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/build-profile.json5 b/feature/recorder/oh_modules/@ohos/common/build-profile.json5 new file mode 100644 index 0000000..7374b5c --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/build-profile.json5 @@ -0,0 +1,17 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + } + } + } + }, + ] +} diff --git a/feature/recorder/oh_modules/@ohos/common/hvigorfile.js b/feature/recorder/oh_modules/@ohos/common/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/feature/recorder/oh_modules/@ohos/common/index.ets b/feature/recorder/oh_modules/@ohos/common/index.ets new file mode 100644 index 0000000..af9c605 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/index.ets @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { default as ConfigData } from './src/main/ets/utils/ConfigData' + +export { default as Util } from './src/main/ets/utils/Util' + +export { default as LogUtil } from './src/main/ets/utils/LogUtil' diff --git a/feature/recorder/oh_modules/@ohos/common/oh-package.json5 b/feature/recorder/oh_modules/@ohos/common/oh-package.json5 new file mode 100644 index 0000000..3159c13 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "index.ets", + "version": "1.0.0", +} diff --git a/feature/recorder/oh_modules/@ohos/common/package.json b/feature/recorder/oh_modules/@ohos/common/package.json new file mode 100644 index 0000000..dfbf6f7 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/hap": "^3.0.0" + } +} diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets b/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets new file mode 100644 index 0000000..728136a --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 class ConfigData { + WH_100_100 = '100%'; + WH_50_100 = '50%'; + WH_40_100 = '40%'; + WH_20_100 = '20%'; +} + +let configData = new ConfigData(); + +export default configData as ConfigData; \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts b/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts new file mode 100644 index 0000000..bbead9d --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 HiLog from "@ohos.hilog"; + +const DOMAIN = 0x0500; +const TAG = "[Recorder]"; + +/** + * log package tool class + */ +export default class LogUtil { + static debug(msg): void { + HiLog.debug(DOMAIN, TAG, msg); + } + + static log(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static info(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static warn(msg): void { + HiLog.warn(DOMAIN, TAG, msg); + } + + static error(msg): void { + HiLog.error(DOMAIN, TAG, msg); + } +} \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets b/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets new file mode 100644 index 0000000..d7ff070 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 default class Util { + + /** + * Time format is converted to seconds + * + * @param timestamp + * @param hasHour + */ + static timeFormat(timestamp: number, hasHour: boolean = true): string { + if (timestamp < 0) { + return ""; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hasHour || hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + return timeStr; + } + + /** + * Time format is converted to milliseconds + * + * @param timestamp + */ + static timeFormatMs(timestamp: number): string { + if (timestamp <= 0) { + return "00:00.00"; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + if (hour < 1) { + let mSec = Math.floor(timestamp % 1000 / 10); + timeStr += "." + Util.addZero(mSec); + } + return timeStr; + } + + /** + * Gets the date at the specified time + * + * @param date + */ + static getDateFormat(date: number): string { + let nowDate = new Date(date); + return nowDate.getFullYear() + "/" + Util.addZero(nowDate.getMonth() + 1) + "/" + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the specified time + * + * @param date + */ + static getTimeFormat(date: number): string { + let nowDate = new Date(date); + return Util.addZero(nowDate.getHours()) + ":" + Util.addZero(nowDate.getMinutes()) + ":" + Util.addZero(nowDate.getSeconds()); + } + + /** + * Gets the current time date + */ + static getDate(): string { + let nowDate = new Date(); + return nowDate.getFullYear() + Util.addZero(nowDate.getMonth() + 1) + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the current time + */ + static getTime(): string { + let nowDate = new Date(); + return Util.addZero(nowDate.getHours()) + Util.addZero(nowDate.getMinutes()) + Util.addZero(nowDate.getSeconds()); + } + + /** + * If the number is less than 10, add "0". + * + * @param num + */ + static addZero(num: number): string{ + return (num < 10 ? "0" + num : num).toString(); + } +} \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/module.json5 b/feature/recorder/oh_modules/@ohos/common/src/main/module.json5 new file mode 100644 index 0000000..56a91a8 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "common", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json new file mode 100644 index 0000000..ffe7272 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json @@ -0,0 +1,32 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "background_color", + "value": "#F1F3F5" + }, + { + "name": "shadow_color", + "value": "#11000000" + }, + { + "name": "pointer_color", + "value": "#007DFF" + }, + { + "name": "warn_color", + "value": "#FF595A" + }, + { + "name": "hint_color", + "value": "#007DFF" + }, + { + "name": "text_color", + "value": "#182431" + } + ] +} \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json new file mode 100644 index 0000000..2375b2d --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + }, + { + "name": "title", + "value": "录音机" + }, + { + "name": "search_recording_files", + "value": "搜索录音文件" + }, + { + "name": "mark", + "value": "标记" + }, + { + "name": "pause", + "value": "暂停" + }, + { + "name": "continue_record", + "value": "继续" + }, + { + "name": "predict_hint", + "value": "预计还能录制10小时以上" + }, + { + "name": "delete_hint", + "value": "是否删除此条录音?" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "delete", + "value": "删除" + }, + { + "name": "has_call_hint", + "value": "通话状态无法录音" + }, + { + "name": "recording_hint", + "value": "录音机正在录音" + }, + { + "name": "suspend_record_hint", + "value": "录音机暂停录音" + } + ] +} diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png new file mode 100644 index 0000000000000000000000000000000000000000..41c12ccb5bb90cd9c05508690ca0b88f33e96008 GIT binary patch literal 3806 zcmdUx2~bnl8pm&BS5adC7Z5~>5L6UdB&-z>DkwaWML?iHA+kjRN!X!QL|N6MD42i* zNkBA$VGZKKs>CG5Kp=!Q2m}Zqpe(Yaw4Kf?4?EMD&YOAf+&Oda{hxFHzwbNe%$-lz zA?yRTSzDg81VA7F0IgntkPDcvzWuZItI0oeSp8b~5&%mAG!R?_v=7(-28n<{!UjNL zHAs=)yn#O&NJ3IfN>qH~>ZsMW)g(ZoBAXyZ@uqj(tb9cd2}%YL;=kX=>GI_v(WDiur@FdIyO~h>DA> zj+uj3V~`L7ZIY4%iTys|SBMx`SzJQv_!+P5vPX5Cypiae*en8CO-cj|m;x(r0hB`DpGdzydeLHr7k|tdD79%Ir8U)OFEHjn z#?9V$lHBFfY$ON36BN%Huf&2#lO&3rFDc%@Eo1|q`t3TKuLwtmo`)^Jv_p0j@SH6N z)^Z9Gkk{ti4|kW;+ds>-=vI5$Zi+ip1w#4W|BBH%X=j)xY^6`FN?<>AARk$>hGSo+ z-w;i@GtuEy6u*s<> z3p&#JM2&guq@bKJY=Z#YcU}03(>h6fcYCK_e4#kV`MI+U>rzDVDUQXNPY1Hga83SY z5B-wLk_EivBD{JTAt}Y}^mK|fzNOf><*zpcDg;haPTz4IN(EEhLbAuwp^u7w+V;1j zQD~>fS4mA6$~?2?cLl9YyR{@;OL44Vv0`U{a|Zw3gIU+%nSx3{Gqr48R-1eMuSNC4 zXgFTB4-MBeXu4-KW|@)5+NS&E(cEL@a3bRECv*!Yz9V-ym%bdo!^dcj;={p)TSvT@ zg$kCrKPPh>Rn?7PLHY=R98Ia(BHv&*)6eWFJ1J_v#>$gr`3lFQi{w`^fq2N2shIzh z2pnuO%4yi{;bYm*$!Ql(oAy|YT=rB-hIZ{pxBMwo8(vcz%*Ow&xCSV_9R= z(g)s>T|SXyf+$ctNJ+}xd*sATTLl;`o(rAGf}2X!XThVteXdnVIg-=AFzyn93P@o4 zlN@qVac^ne|u25+A1zJ4u=O8po*_yqlk%Z_Xbbp4-P5 zUE%a`5ip~yHjCaYcPnEg$zK0(gu^}#e}@{KD~UDN~t7S7SeUC=?t z1gjRFIAh#^+5f0YC%+EjLiC0jz3umZR8vF@&e=P9TWhx5yI+g@GK0$+T3yw83cCn5 zwjF&mC-t*azjmJ^oZP|ca!;M<8M*Fci6nI zjOA7~Y&<4gzA?AliO65L#$h&cW|m@4qZ>P}pRjW`h3UV5@JGh3-z&251)bd_8(zE* zYbXof(HsVyz=q{EJ7B3U-?hwlazm0-AziMoM_*JVW$?DA`a_jva{NsD)3{miWlnt; zB?1>ho$l0!V|v+a#g#2pao8Zm|J=Ff&tqOzOJf$|u8?8WR@EFLP0s8vbyMV0lPT>p zBbB0&p%l_I&UlP9S&~OC>!t7NuKrBE%0W#TS`99QnO^>W3Zue2+ipj2lcAZlPJ z*JSVc#G1&!p+i}8`=!KpDatzsuRMD|oUb#r-J(AIW}XDq5(1kMT~yNvy5bN=nBW#~%7*UeLr8QKJ&yG;En(eXf%qa9GzJ zQDN}P$As4%gV$`2sHNTN;nh)F2u&I(yPjP{O|pDs4oOW@|8e~-MMxD zSPA*dg}73S&nL8db6=SpKNZ?AK9cN{QQBb}i9$EnMfJwI22^;A({(w#D;~3CrewV> zf}Yc0?VyiUvZUQJ8JCaEeWPZ@Vpg`F-qI6&l*8FIJDq1Z`u?`t;jvHLiR0>t^!+A;Y`#FOnC&;eUzJ`!bTpW%#)ns+jaRsKvV47yB;9-HUy#x{Zy( zA7$MmYs{h)5L@t=Mo60sBQ9QaK}?GZsU$$tZJWJdgUoiYF~8R-`|+Kcury3Wo_r_6 zLPZ)@V-O97{)-n9E3X%{SQb1R{|!#b&a&5C$1qYrh5rEOwpa|B_|Fpmg6HvHP6$MAVKP4$llI;+cX@w}YKwSV%z1~5Fi7Ic*g2dvURZ*BkZC?>+jExyGu)Ffe8=j% z#a#Zs4@$ztK;vzxIzxgHfklD2^jN{IbBOV-WjHu9LN}#t+9E!CF3*1^NC@Orb;NrH zW_5r5(J9&_Oq@DKgifu!II_h5K>cF_2~_YWUc9@r8%Y}zF{w!r12*j3$`+=&g*>5YfC zQ;zM<1UIR4qh4U@rLCu9A*dYc`4v<}pBOXq$Mrtzm9=&8TF(DO{VnzmC}{k9eVX;> zy8Kyn(<42$yYjM2$k|iwQ`+ZrViRw^i;{3d80ghCv5WUe-!C`ok0@bfUk@ee;BX3? zNNs$aYA_*iI%;2XdCJKX;cg!qWf|p+V*r9#LwjIug}$42E4D^g&c-s>q-`TipKQiA zOR{$8R>!A>A8?cmxN>%`&0UiFBvEEq`chYh)j6_yhSk{pE5=4zenYdPv7twPQ(mb;I9 literal 0 HcmV?d00001 diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg new file mode 100644 index 0000000..6f7f039 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg @@ -0,0 +1,10 @@ + + + systemicon/back + + + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg new file mode 100644 index 0000000..3ec94e4 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg @@ -0,0 +1,8 @@ + + + ic_clock_add + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg new file mode 100644 index 0000000..14a0ba5 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg @@ -0,0 +1,10 @@ + + + ic_clock_enhance + + + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg new file mode 100644 index 0000000..330eda7 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg @@ -0,0 +1,8 @@ + + + ic_clock_mark + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg new file mode 100644 index 0000000..4a6c569 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg @@ -0,0 +1,7 @@ + + + ic_clock_play + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg new file mode 100644 index 0000000..c8f7906 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg @@ -0,0 +1,7 @@ + + + ic_clock_record + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg new file mode 100644 index 0000000..0296449 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg @@ -0,0 +1,7 @@ + + + ic_clock_stop + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg new file mode 100644 index 0000000..bf6f0ea --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg @@ -0,0 +1,8 @@ + + + ic_clock_suspend + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg new file mode 100644 index 0000000..34c0e94 --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg @@ -0,0 +1,8 @@ + + + ic_record_play + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg new file mode 100644 index 0000000..1b2a8aa --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg @@ -0,0 +1,8 @@ + + + ic_record_search + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg new file mode 100644 index 0000000..2b7ceaa --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg @@ -0,0 +1,9 @@ + + + ic_record_stop + + + + + + \ No newline at end of file diff --git a/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg new file mode 100644 index 0000000..400c3ef --- /dev/null +++ b/feature/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg @@ -0,0 +1,13 @@ + + + public_more + + + + + + + + + + \ No newline at end of file diff --git a/feature/recorder/src/main/ets/controller/AudioController.ets b/feature/recorder/src/main/ets/controller/AudioController.ets index 8124718..2b1cae6 100644 --- a/feature/recorder/src/main/ets/controller/AudioController.ets +++ b/feature/recorder/src/main/ets/controller/AudioController.ets @@ -16,6 +16,7 @@ import mediaLibrary from '@ohos.multimedia.mediaLibrary'; import media from '@ohos.multimedia.media'; import { LogUtil } from '@ohos/common'; +import { BusinessError, Callback } from '@ohos.base' export enum AudioState { /** @@ -36,24 +37,23 @@ const NOTIFY_INTERVAL_MS = 50; const TAG = "AudioController : "; export class AudioController { - private audioPlayer: media.AudioPlayer = undefined; - private state: AudioState = AudioState.IDLE; - private playFile: mediaLibrary.FileAsset = undefined; + private audioPlayer?: media.AVPlayer; + private state: string = 'idle'; + private playFile: string = ''; private dataLoad: boolean = false; - private finishListener: () => void = undefined; private currentTimeMs: number = 0; private intervalId: number = -1; - private timeUpdateListener: (currentTimeMs: number) => void = undefined; - private stateUpdateListener: (AudioState) => void = undefined; + private timeUpdateListener?: Callback; + private stateUpdateListener?: Callback; /** * Set the time update listener * * @param listener */ - public setTimeUpdateListener(listener: (currentTimeMs: number) => void) { + public setTimeUpdateListener(tag: string, timeUpdateListener: Callback): void { LogUtil.info(`${TAG} setTimeUpdateListener`); - this.timeUpdateListener = listener; + this.timeUpdateListener = timeUpdateListener; } /** @@ -61,9 +61,9 @@ export class AudioController { * * @param listener */ - public setStateUpdateListener(listener: (AudioState) => void) { + public setStateUpdateListener(tag: string, setStateUpdateListener: Callback): void { LogUtil.info(`${TAG} setStateUpdateListener`); - this.stateUpdateListener = listener; + this.stateUpdateListener = setStateUpdateListener; } /** @@ -91,70 +91,54 @@ export class AudioController { * @param playSrc * @param callback */ - initAudioPlayer(playSrc: mediaLibrary.FileAsset, callback: () => void) { + async initAudioPlayer(playSrc: string, callback: () => void) { LogUtil.info(`${TAG} initAudioPlayer`); this.playFile = playSrc; this.dataLoad = false; this.release(); LogUtil.info(`${TAG} createAudioPlayer`); - this.audioPlayer = media.createAudioPlayer(); - this.audioPlayer.on('dataLoad', () => { - this.dataLoad = true; - LogUtil.info(`${TAG} audioPlayer dataLoad success`); - if (callback) { - callback(); - } - }) - this.audioPlayer.on('stop', () => { - LogUtil.info(`${TAG} audioPlayer stop success`); - this.release(); - }) - this.audioPlayer.on('error', (error) => { - LogUtil.error(`${TAG} audioPlayer error. info:${error}`); - }) - this.audioPlayer.on('timeUpdate', (num) => { - LogUtil.info(`${TAG} audioPlayer timeUpdate. time:${num}`); - }) - this.audioPlayer.on('audioInterrupt', (num) => { - LogUtil.warn(`${TAG} audioPlayer audioInterrupt. time:${num}`); - }) - this.audioPlayer.on('finish', () => { - LogUtil.info(`${TAG} audioPlayer finish.`); - clearInterval(this.intervalId); - this.intervalId = -1; - this.state = AudioState.IDLE; - this.notifyStateChanges(); - }) - LogUtil.info(`${TAG} audioPlayer reset.`) - this.audioPlayer.reset(); - LogUtil.info(`${TAG} read FileAsset`); - let fdPath = playSrc.open('r'); - fdPath.then(fdNumber => { - LogUtil.info(`${TAG} audioPlayer set src`); - this.audioPlayer.src = `fd://${fdNumber}`; - }); + if (!this.audioPlayer) { + return; + } + try { + this.audioPlayer = await media.createAVPlayer(); + } catch (e) { + } + this.audioPlayer?.on('stateChange', this.stateChangeListener) } + private stateChangeListener = async (state: string, reason: media.StateChangeReason) => { + if (!this.audioPlayer) { + return; + } + this.state = state; + switch (state) { + case 'idle' : + break; + case 'initialized': + break; + case 'playing': + break; + case 'prepared': + break; + case 'paused': + break; + case 'completed': + break; + case 'stopped': + case 'released': + break; + } + } /** * audioPlayer play */ play() { - if (typeof (this.audioPlayer) != `undefined`) { - this.audioPlayer.on('play', () => { - LogUtil.info(`${TAG} audioPlayer play success`); - this.startTimer(); - }); - if (this.dataLoad) { - LogUtil.info(`${TAG} audioPlayer play`); + try { + if (this.audioPlayer) { this.audioPlayer.play(); - } else { - this.audioPlayer.on('dataLoad', () => { - LogUtil.info(`${TAG} audioPlayer dataLoad success`); - this.dataLoad = true; - LogUtil.info(`${TAG} audioPlayer play`); - this.audioPlayer.play(); - }); } + } catch (e) { } } @@ -164,7 +148,7 @@ export class AudioController { * @param timeMs */ seek(timeMs: number) { - if (typeof (this.audioPlayer) != `undefined`) { + if (this.audioPlayer) { LogUtil.info(`${TAG} audioPlayer time to jump. time:` + timeMs); this.audioPlayer.seek(timeMs); } @@ -174,11 +158,7 @@ export class AudioController { * audioPlayer pause */ pause() { - if (typeof (this.audioPlayer) != `undefined`) { - this.audioPlayer.on('pause', () => { - LogUtil.info(`${TAG} audioPlayer pause success`); - this.stopTimer(); - }); + if (this.audioPlayer) { LogUtil.info(`${TAG} audioPlayer pause`); this.audioPlayer.pause(); } @@ -188,11 +168,10 @@ export class AudioController { * audioPlayer stop */ stop() { - if (typeof (this.audioPlayer) != `undefined` && this.state != AudioState.IDLE) { + if ((this.audioPlayer) && this.state != 'idle') { LogUtil.info(`${TAG} audioPlayer stop`); - this.state = AudioState.IDLE; - this.notifyStateChanges(); - clearInterval(this.intervalId); + this.state = 'idle'; + this.audioPlayer.release(); this.intervalId = -1; } } @@ -201,47 +180,17 @@ export class AudioController { * audioPlayer continue play */ continuePlay() { - if (typeof (this.audioPlayer) != `undefined`) { + if (this.audioPlayer) { LogUtil.info(`${TAG} audioPlayer continue play`); this.audioPlayer.play(); } } - /** - * startTimer - */ - startTimer() { - if (this.intervalId != -1) { - return; - } - this.state = AudioState.RUNNING; - this.notifyStateChanges(); - LogUtil.info(`${TAG} audioPlayer show time update start`); - this.intervalId = setInterval(() => { - this.currentTimeMs = this.audioPlayer.currentTime; - this.notifyTimeChanges(); - }, NOTIFY_INTERVAL_MS); - } - - /** - * stopTimer - */ - stopTimer() { - if (this.intervalId == -1) { - return; - } - this.state = AudioState.PAUSED; - this.notifyStateChanges(); - LogUtil.info(`${TAG} audioPlayer show time update stop`); - clearInterval(this.intervalId); - this.intervalId = -1; - } - /** * audioPlayer release */ release() { - if (typeof (this.audioPlayer) != `undefined`) { + if (this.audioPlayer) { this.currentTimeMs = 0; this.notifyTimeChanges(); LogUtil.info(`${TAG} audioPlayer release`); diff --git a/feature/recorder/src/main/ets/controller/MediaController.ets b/feature/recorder/src/main/ets/controller/MediaController.ets index 103d072..db8262d 100644 --- a/feature/recorder/src/main/ets/controller/MediaController.ets +++ b/feature/recorder/src/main/ets/controller/MediaController.ets @@ -21,28 +21,14 @@ import { LogUtil } from '@ohos/common'; const TAG = 'MediaController : '; -class MediaController { +export class MediaController { private mMediaLibrary: mediaLibrary.MediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext); - private preferences: data_preferences.Preferences = undefined; + private preferences?: data_preferences.Preferences; constructor() { this.initPreferences(); } - /** - * delete Record - * - * @param deleteRecordUri - * @param callback - */ - deleteRecord(deleteRecordUri: string, callback: () => void) { - LogUtil.info(`${TAG} delete Asset. uri: ${deleteRecordUri}`) - this.mMediaLibrary.deleteAsset(deleteRecordUri).then(() => { - LogUtil.info(`${TAG} delete Asset successs.`); - callback(); - }); - } - /** * init Preferences */ @@ -65,56 +51,6 @@ class MediaController { LogUtil.info(`${TAG} save File Duration end.`); } } - - /** - * get File Duration from preferences - * - * @param name - */ - async getFileDuration(name: string) { - LogUtil.info(`${TAG} getFileDuration. fileName : ${name}.`); - return this.preferences.get(name, 0); - } - - /** - * query All Audios - */ - async queryAllAudios() { - LogUtil.info(`${TAG} queryAllAudios`); - let fileKeyObj = mediaLibrary.FileKey; - let fetchOp = { - selections: `${fileKeyObj.MEDIA_TYPE}=?`, - selectionArgs: [`${mediaLibrary.MediaType.AUDIO}`], - } - LogUtil.info(`${TAG} getFileAssets`); - const fetchFileResult = await this.mMediaLibrary.getFileAssets(fetchOp); - LogUtil.info(`${TAG} Assets count : ${fetchFileResult.getCount()}`); - let result: Array = []; - if (fetchFileResult.getCount() > 0) { - let fileAssets = await fetchFileResult.getAllObject(); - for (let i = 0; i < fileAssets.length; i++) { - let record = new RecordData(fileAssets[i]); - if (record.duration == 0) { - await record.getDuration(); - } - result.push(record); - } - } - return result; - } - - /** - * create Audio File - */ - async createAudioFile() { - LogUtil.info(`${TAG} createAudioFile`); - this.mMediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext); - let displayName = Util.getDate() + "_" + Util.getTime() + ".m4a"; - LogUtil.info(`${TAG} displayName : ${displayName}`); - let publicPath = await this.mMediaLibrary.getPublicDirectory(mediaLibrary.DirectoryType.DIR_AUDIO); - LogUtil.info(`${TAG} publicPath : ${publicPath}`); - return await this.mMediaLibrary.createAsset(mediaLibrary.MediaType.AUDIO, displayName, publicPath); - } } export default new MediaController(); \ No newline at end of file diff --git a/feature/recorder/src/main/ets/controller/RecordController.ets b/feature/recorder/src/main/ets/controller/RecordController.ets index 6dc9992..ec15a77 100644 --- a/feature/recorder/src/main/ets/controller/RecordController.ets +++ b/feature/recorder/src/main/ets/controller/RecordController.ets @@ -16,21 +16,12 @@ import media from '@ohos.multimedia.media'; import { LogUtil } from '@ohos/common'; import Notification from '@ohos.notification'; +import { BusinessError, Callback } from '@ohos.base' const NOTIFY_INTERVAL_MS = 60; const NOTIFY_ID = 10023; const TAG = 'RecordController : '; -let audioConfig = { - audioEncodeBitRate: 22050, - audioSampleRate: 22050, - numberOfChannels: 2, - uri: '', - location: { latitude: 31, longitude: 118 }, - audioEncoderMime: media.CodecMimeType.AUDIO_AAC, - fileFormat: media.ContainerFormatType.CFT_MPEG_4A, -} - export enum RecordState { IDLE, RUNNING, @@ -41,11 +32,15 @@ export class RecordController { private beforePauseTime: number = 0; private startTimestamp: number = 0; private notifierId: number = -1; - private state: RecordState = RecordState.PAUSED; + private state: string = ''; + private config?: media.AVRecorderConfig; + private openedFileFd?: number; + private currentFilePath?: string; + private recorderDuration: number = 0; private currentTimeMs: number = 0; - private audioRecorder: media.AudioRecorder = undefined; - private timeUpdateListener: (currentTimeMs: number) => void = undefined; - private stateUpdateListener: (RecordState) => void = undefined; + private audioRecorder?: media.AVRecorder; + private timeUpdateListener?: Callback; + private stateUpdateListener?: Callback; /** * Notification time update @@ -71,9 +66,9 @@ export class RecordController { * * @param listener */ - public setTimeUpdateListener(listener: (currentTimeMs: number) => void) { - LogUtil.info(`${TAG} setTimeUpdateListener.`); - this.timeUpdateListener = listener; + public setTimeUpdateListener(tag: string, timeUpdateListener: Callback): void { + LogUtil.info(`${TAG} setTimeUpdateListener`); + this.timeUpdateListener = timeUpdateListener; } /** @@ -81,58 +76,53 @@ export class RecordController { * * @param listener */ - public setStateUpdateListener(listener: (RecordState) => void) { - LogUtil.info(`${TAG} setStateUpdateListener.`); - this.stateUpdateListener = listener; + public setStateUpdateListener(tag: string, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; } /** * init AudioRecorder */ - initAudioRecorder() { + async initAudioRecorder() { LogUtil.info(`${TAG} initAudioRecorder.`); - let recording_hint - let suspend_record_hint - globalThis.abilityContext.resourceManager.getString($r('app.string.recording_hint').id).then((value) => { - recording_hint = value - }) - globalThis.abilityContext.resourceManager.getString($r('app.string.suspend_record_hint').id).then((value) => { - suspend_record_hint = value - }) - this.audioRecorder = media.createAudioRecorder(); - this.audioRecorder.on('prepare', () => { - LogUtil.info(`${TAG} audioRecorder prepare success.`); - this.audioRecorder.start(); - }); - this.audioRecorder.on('start', () => { - LogUtil.info(`${TAG} audioRecorder start success.`); - this.publishNotification(recording_hint) - this.startTime(); - }); - this.audioRecorder.on('pause', () => { - LogUtil.info(`${TAG} audioRecorder pause success`); - this.publishNotification(suspend_record_hint) - clearInterval(this.notifierId); - this.notifierId = -1; - this.beforePauseTime += new Date().getTime() - this.startTimestamp; - this.state = RecordState.PAUSED; - this.notifyStateChanges(); - }); - this.audioRecorder.on('resume', () => { - LogUtil.info(`${TAG} audioRecorder resume success`); - this.publishNotification(recording_hint) - this.startTime(); + if (!this.audioRecorder) { + this.audioRecorder = await media.createAVRecorder(); + } + this.setAVRecorderCallback(this.audioRecorder); + } + + private setAVRecorderCallback(avRecorder: media.AVRecorder): void { + if (!avRecorder) { + return; + } + avRecorder.on('error', async (err: BusinessError) => { + }); - this.audioRecorder.on('stop', () => { - LogUtil.info(`${TAG} audioRecorder stop success`); - this.logoutNotification() - this.audioRecorder.release(); - clearInterval(this.notifierId); - this.notifierId = -1; - this.state = RecordState.IDLE; - this.currentTimeMs = 0; - this.notifyStateChanges(); - this.notifyTimeChanges(); + avRecorder.on('stateChange', async (state: string, resaon: media.StateChangeReason) => { + this.state = state; + switch (state) { + case 'idle': + break; + case 'initialized': + break; + case 'started': + break; + case 'prepared': + break; + case 'paused': + break; + case 'completed': + break; + case 'stopped': + break; + case 'released': + break; + case 'released': + break; + default: + break + } }); } @@ -148,36 +138,30 @@ export class RecordController { * * @param pathName */ - startRecorder(pathName) { - if (typeof (this.audioRecorder) != 'undefined') { - audioConfig.uri = pathName; + startRecorder(tag: string, filefd: number, filePath: string, config: media.AVRecorderConfig, + recorderStateCallback: Callback, onErrorCallback?: Callback) { + if (this.audioRecorder) { + this.recorderDuration = 0; + this.currentFilePath = filePath; + this.config = config; + this.openedFileFd = filefd; + if (this.audioRecorder.state === 'idle') { + this.audioRecorder.prepare(config); + } else { + this.audioRecorder.reset(); + } LogUtil.info(`${TAG} audioRecorder prepare.`); - this.audioRecorder.prepare(audioConfig); + ; } else { LogUtil.error(`${TAG} case failed, audioRecorder is null.`); } } - /** - * start Time - */ - startTime() { - this.state = RecordState.RUNNING; - this.startTimestamp = new Date().getTime(); - LogUtil.info(`${TAG} audioRecorder show time update start`); - this.notifierId = setInterval(() => { - let timestamp = new Date().getTime(); - this.currentTimeMs = this.beforePauseTime + timestamp - this.startTimestamp; - this.notifyTimeChanges(); - }, NOTIFY_INTERVAL_MS); - this.notifyStateChanges(); - } - /** * Recorder pause */ pause() { - if (typeof (this.audioRecorder) != `undefined`) { + if (this.audioRecorder) { LogUtil.info(`${TAG} audioRecorder pause`); this.audioRecorder.pause(); } @@ -187,7 +171,7 @@ export class RecordController { * Recorder resume */ resume() { - if (typeof (this.audioRecorder) != `undefined`) { + if (this.audioRecorder) { LogUtil.info(`${TAG} audioRecorder resume`); this.audioRecorder.resume(); } @@ -196,38 +180,10 @@ export class RecordController { /** * Recorder stop */ - stop(callback?) { - if (typeof (this.audioRecorder) != `undefined`) { + stop() { + if (this.audioRecorder) { LogUtil.info(`${TAG} audioRecorder stop`); this.audioRecorder.stop(); - if (callback) { - callback(); - } } } - - /** - * publish Notification - */ - publishNotification(text) { - var notificationRequest = { - id: NOTIFY_ID, - content: { - contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, - normal: { - title: text, - text: ``, - additionalText: `` - } - } - } - Notification.publish(notificationRequest) - } - - /** - * logout Notification - */ - logoutNotification() { - Notification.cancel(NOTIFY_ID) - } } \ No newline at end of file diff --git a/feature/recorder/src/main/ets/controller/StateController.ets b/feature/recorder/src/main/ets/controller/StateController.ets index b8c1ea6..bf5bc9a 100644 --- a/feature/recorder/src/main/ets/controller/StateController.ets +++ b/feature/recorder/src/main/ets/controller/StateController.ets @@ -14,6 +14,7 @@ */ import { LogUtil } from '@ohos/common'; +import { BusinessError, Callback } from '@ohos.base' const TAG = 'ControlState : '; @@ -23,16 +24,17 @@ export enum ControlState { } export class StateController { - private state: ControlState = ControlState.END; - private stateUpdateListener: (RecordState) => void = undefined; + private state: number = 1; + private stateUpdateListener?: Callback; /** * Set the status update listener * * @param listener */ - public setStateUpdateListener(listener: (RecordState) => void) { - this.stateUpdateListener = listener; + public setStateUpdateListener(tag: number, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; } /** diff --git a/feature/recorder/src/main/ets/model/RecordData.ets b/feature/recorder/src/main/ets/model/RecordData.ets index 60e9662..ab6a485 100644 --- a/feature/recorder/src/main/ets/model/RecordData.ets +++ b/feature/recorder/src/main/ets/model/RecordData.ets @@ -13,32 +13,31 @@ * limitations under the License. */ -import { default as MediaController } from '../controller/MediaController'; +import { MediaController } from '../controller/MediaController'; import mediaLibrary from '@ohos.multimedia.mediaLibrary'; export class RecordData { - fileAsset: mediaLibrary.FileAsset; - title: string; - duration: number; - date: number; + fileAsset: string = ''; + title: string = ''; + duration: number = 0; + date: number = 0; - constructor(fileAsset: mediaLibrary.FileAsset) { - this.fileAsset = fileAsset; + constructor(fileAsset: number, date: number, title: string) { if (fileAsset) { - if (fileAsset.duration > 0) { - this.duration = fileAsset.duration; + if (fileAsset > 0) { + this.duration = fileAsset; } else { this.duration = 0; } - this.date = fileAsset.dateAdded; - this.title = fileAsset.title; + if (date > 0) { + this.date = date; + } else { + this.date = 0; + } + this.title = title; } else { this.duration = 0; this.title = ''; } } - - async getDuration() { - this.duration = Number(await MediaController.getFileDuration(this.fileAsset.title)); - } } \ No newline at end of file diff --git a/hvigor/hvigor-config.json5 b/hvigor/hvigor-config.json5 new file mode 100644 index 0000000..566ae69 --- /dev/null +++ b/hvigor/hvigor-config.json5 @@ -0,0 +1,11 @@ +{ + "modelVersion": "5.0.2", + "dependencies": { + // "@ohos/hypium-plugin": "1.0.8-rc7", + // "fs-extra": "10.0.1", + // "execa": "5.1.1" + }, + "debugging": { + "stacktrace": true + } +} \ No newline at end of file diff --git a/oh-package-lock.json5 b/oh-package-lock.json5 new file mode 100644 index 0000000..120748e --- /dev/null +++ b/oh-package-lock.json5 @@ -0,0 +1,20 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hypium@1.0.9": "@ohos/hypium@1.0.9" + }, + "packages": { + "@ohos/hypium@1.0.9": { + "name": "@ohos/hypium", + "version": "1.0.9", + "integrity": "sha512-qW5HE293s8+YRwh+6reJjR1Q08iuhay2RdPJ/JJWOI9/mjHn/zMW4i/CUfhvqlAD2w+PXUfwAYoXItc4OQpo6A==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.9.tgz", + "shasum": "c0b869cd51c7eb0764f90cb1a5b231d5512cef97", + "registryType": "ohpm" + } + } +} \ No newline at end of file diff --git a/oh-package.json5 b/oh-package.json5 new file mode 100644 index 0000000..b6837c2 --- /dev/null +++ b/oh-package.json5 @@ -0,0 +1,20 @@ +{ + "modelVersion": "5.0.2", + "license": "ISC", + "devDependencies": {}, + "name": "ohosrecorder", + "ohos": { + "org": "huawei", + "directoryLevel": "project", + "buildTool": "hvigor" + }, + "description": "example description", + "repository": {}, + "version": "1.0.0", + "modelVersion": "5.0.2", + "dependencies": { + "@ohos/hypium": "1.0.9", + // "@ohos/hvigor-ohos-plugin":"1.1.6", + // "@ohos/hvigor":"1.1.6" + } +} \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/CHANGELOG.md b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/CHANGELOG.md new file mode 100644 index 0000000..79c11d2 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/CHANGELOG.md @@ -0,0 +1,50 @@ +## 1.0.9 + +- 测试hook方法支持断言与异常 +- 修复不能mock静态方法的问题 + +## 1.0.6 + +- 适配模块化编译 +- 适配IDE覆盖率数据输出 + +## 1.0.5 + +- 优化接口异常场景处理能力 +- 修复大规模压力测试下内存溢出问题 +- 修复测试脚本定义扩展原型方法与框架的兼容性问题 +- 异步promise状态判断断言与取反断言兼容 + +## 1.0.4 + +- 新增异步promise状态判断断言 +- 新增基础数据判断断言 +- 新增断言异常信息描述 +- 优化用例计时逻辑,采用相对时间计时 +- 修改用例执行过程,异步执行 +- 修复用例结果偶现的乱序问题 + +## 1.0.3 + +- 新增mock对象的能力,支持mock无参数函数 +- 新增测试套、测试用例随机执行功能 +- 解决测试套声明不规范,导致用例加载异常的问题 +- 修复命令行窗口输出乱序的问题 + +## 1.0.2 + +- 新增mock接口,判断当前mock方法状态、使用次数 +- 修复用例耗时统计问题 +- 修改断言功能,断言失败后,会抛出异常 + +## 1.0.1 +- 新增mock基础能力 +- 修复部分断言失败后,消息提示异常问题 + +## 1.0.0 +- 新增应用日志关键字查询接口,查询hilog日志中是否包含指定字符串 +- 支持用例筛选功能,用于指定测试用例的执行。可按用例名称、类型、规模、级别与测试套名称筛选 +- 支持新SDK下单元测试 +- 支持dry run 功能,通过命令行传参数,返回当前测试套用例名称全集 +- 新增框架接口声明文件,用于deveco联想 +- 修复用例状态统计问题 \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/LICENSE b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/LICENSE new file mode 100644 index 0000000..4947287 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/README.md b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/README.md new file mode 100644 index 0000000..83ddccc --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/README.md @@ -0,0 +1,219 @@ +
Hypium
+
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.9" +} +``` +注: +hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导: +[Deveco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio) + +#### 通用语法 + +- 测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。 + +| No. | API | 功能说明 | +| --- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数 | +| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 | +| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 | +| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 | +| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 | +| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数 | +| 7 | expect | 支持bool类型判断等多种断言方法 | + +#### 断言库 + +- 示例代码: + +```javascript + expect(${actualvalue}).assertX(${expectvalue}) +``` + +- 断言功能列表: + +| No. | API | 功能说明 | +| :--- | :------------------------------- | ---------------------------------------------------------------------------------------------- | +| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1) | +| 2 | assertContain | 检验actualvalue中是否包含expectvalue | +| 3 | assertDeepEquals | @since1.0.4 检验actualvalue和expectvalue(0)是否是同一个对象 | +| 4 | assertEqual | 检验actualvalue是否等于expectvalue[0] | +| 5 | assertFail | 抛出一个错误 | +| 6 | assertFalse | 检验actualvalue是否是false | +| 7 | assertTrue | 检验actualvalue是否是true | +| 8 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 | +| 9 | assertLarger | 检验actualvalue是否大于expectvalue | +| 10 | assertLess | 检验actualvalue是否小于expectvalue | +| 11 | assertNaN | @since1.0.4 检验actualvalue是否是NaN | +| 12 | assertNegUnlimited | @since1.0.4 检验actualvalue是否等于Number.NEGATIVE_INFINITY | +| 13 | assertNull | 检验actualvalue是否是null | +| 14 | assertPosUnlimited | @since1.0.4 检验actualvalue是否等于Number.POSITIVE_INFINITY | +| 15 | assertPromiseIsPending | @since1.0.4 检验actualvalue是否处于Pending状态【actualvalue为promse对象】 | +| 16 | assertPromiseIsRejected | @since1.0.4 检验actualvalue是否处于Rejected状态【同15】 | +| 17 | assertPromiseIsRejectedWith | @since1.0.4 检验actualvalue是否处于Rejected状态,并且比较执行的结果值【同15】 | +| 18 | assertPromiseIsRejectedWithError | @since1.0.4 检验actualvalue是否处于Rejected状态并有异常,同时比较异常的类型和message值【同15】 | +| 19 | assertPromiseIsResolved | @since1.0.4 检验actualvalue是否处于Resolved状态【同15】 | +| 20 | assertPromiseIsResolvedWith | @since1.0.4 检验actualvalue是否处于Resolved状态,并且比较执行的结果值【同15】 | +| 21 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue | +| 22 | assertUndefined | 检验actualvalue是否是undefined | +| 23 | not | @since1.0.4 断言结果取反 | + + + 示例代码: + +```javascript + import { describe, it, expect } from '@ohos/hypium'; + + export default async function assertCloseTest() { + describe('assertClose', function () { + it('assertClose_success', 0, function () { + let a = 100; + let b = 0.1; + expect(a).assertClose(99, b); + }) + }) + } +``` + +#### 公共系统能力 + +| No. | API | 功能描述 | +| ---- | ------------------------------------------------------- | ------------------------------------------------------------ | +| 1 | existKeyword(keyword: string, timeout: number): boolean | @since1.0.3 hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 | +| 2 | actionStart(tag: string): void | @since1.0.3 cmd窗口输出开始tag | +| 3 | actionEnd(tag: string): void | @since1.0.3 cmd窗口输出结束tag | + + 示例代码: + +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function existKeywordTest() { + describe('existKeywordTest', function () { + it('existKeyword',DEFAULT, async function () { + console.info("HelloTest"); + let isExist = await SysTestKit.existKeyword('HelloTest'); + console.info('isExist ------>' + isExist); + }) + }) +} +``` +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function actionTest() { + describe('actionTest', function () { + it('existKeyword',DEFAULT, async function () { + let tag = '[MyTest]'; + SysTestKit.actionStart(tag); + //do something + SysTestKit.actionEnd(tag); + }) + }) +} +``` + +#### 专项能力 + +- 测试用例属性筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是先在测试用例上标记用例属性后,再在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。 + +| Key | 含义说明 | Value取值范围 | +| -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| level | 用例级别 | "0","1","2","3","4", 例如:-s level 1 | +| size | 用例粒度 | "small","medium","large", 例如:-s size small | +| testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience", 例如:-s testType function | + + 示例代码 + +```javascript +import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium'; + +export default function attributeTest() { + describe('attributeTest', function () { + it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () { + console.info('Hello Test'); + }) + }) +} +``` + + 示例命令 +```shell +XX -s level 1 -s size small -s testType function +``` +该命令的作用是:筛选测试应用中同时满足a)用例级别是1 b)用例粒度是small c)用例测试类型是function 三个条件的用例执行。 + +- 测试套/测试用例名称筛选能力(测试套与用例名称用“#”号连接,多个用“,”英文逗号分隔) + +| Key | 含义说明 | Value取值范围 | +| -------- | ----------------------- | -------------------------------------------------------------------------------------------- | +| class | 指定要执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s class attributeTest#testAttributeIt | +| notClass | 指定不执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s notClass attributeTest#testAttributeIt | + + 示例命令 +```shell +XX -s class attributeTest#testAttributeIt,abilityTest#testAbilityIt +``` +该命令的作用是:筛选测试应用中attributeTest测试套下的testAttributeIt测试用例,abilityTest测试套下的testAbilityIt测试用例,只执行这两条用例。 + +- 其他能力 + +| 能力项 | Key | 含义说明 | Value取值范围 | +| ------------ | ------- | ---------------------------- | ---------------------------------------------- | +| 随机执行能力 | random | 测试套&测试用例随机执行 | true, 不传参默认为false, 例如:-s random true | +| 空跑能力 | dryRun | 显示要执行的测试用例信息全集 | true , 不传参默认为false,例如:-s dryRun true | +| 异步超时能力 | timeout | 异步用例执行的超时时间 | 正整数 , 单位ms,例如:-s timeout 5000 | + +##### 约束限制 +随机执行能力和空跑能力从npm包1.0.3版本开始支持 + +#### Mock能力 + +##### 约束限制 + +单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium/v/1.0.1)开始支持 + +## 约束 + +*** + 本模块首批接口从OpenHarmony SDK API version 8开始支持。 + +## Hypium开放能力隐私声明 + +- 我们如何收集和使用您的个人信息 + 您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。 +- SDK处理的个人信息 + 不涉及。 +- SDK集成第三方服务声明 + 不涉及。 +- SDK数据安全保护 + 不涉及。 +- SDK版本更新声明 + 为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。 + diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.d.ts b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.d.ts new file mode 100644 index 0000000..b0b4394 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.d.ts @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const DEFAULT = 0B0000 + +export const when: when; + +export enum TestType { + FUNCTION = 0B1, + PERFORMANCE = 0B1 << 1, + POWER = 0B1 << 2, + RELIABILITY = 0B1 << 3, + SECURITY = 0B1 << 4, + GLOBAL = 0B1 << 5, + COMPATIBILITY = 0B1 << 6, + USER = 0B1 << 7, + STANDARD = 0B1 << 8, + SAFETY = 0B1 << 9, + RESILIENCE = 0B1 << 10 +} + +export enum Size { + SMALLTEST = 0B1 << 16, + MEDIUMTEST = 0B1 << 17, + LARGETEST = 0B1 << 18 +} + +export enum Level { + LEVEL0 = 0B1 << 24, + LEVEL1 = 0B1 << 25, + LEVEL2 = 0B1 << 26, + LEVEL3 = 0B1 << 27, + LEVEL4 = 0B1 << 28 +} + +export function describe(testSuiteName: string, callback: Function): void + +export function beforeEach(callback: Function): void + +export function afterEach(callback: Function): void + +export function beforeAll(callback: Function): void + +export function afterAll(callback: Function): void + +export function it(testCaseName: string, attribute: (TestType | Size | Level), callback: Function) + +export interface Assert { + assertClose(expectValue: number, precision: number): void + assertContain(expectValue: any): void + assertEqual(expectValue: any): void + assertFail(): void + assertFalse(): void + assertTrue(): void + assertInstanceOf(expectValue: string): void + assertLarger(expectValue: number): void + assertLess(expectValue: number): void + assertNull(): void + assertThrowError(expectValue: string): void + assertUndefined(): void + assertLargerOrEqual(expectValue: number):void + assertLessOrEqual(expectValue: number):void + assertNaN():void + assertNegUnlimited(): void + assertPosUnlimited(): void + not(): Assert; + assertDeepEquals(expectValue: any):void + assertPromiseIsPending(): void + assertPromiseIsRejected(): void + assertPromiseIsRejectedWith(expectValue?: any): void + assertPromiseIsRejectedWithError(...expectValue): void + assertPromiseIsResolved(): void + assertPromiseIsResolvedWith(expectValue?: any): void +} + +export function expect(actualValue?: any): Assert + +export class ArgumentMatchers { + static any; + static anyString; + static anyBoolean; + static anyNumber; + static anyObj; + static anyFunction; + static matchRegexs(Regex: RegExp): void +} + +declare interface when { + afterReturn(value: any): any + afterReturnNothing(): undefined + afterAction(action: any): any + afterThrow(e_msg: string): string + (argMatchers?: any): when; +} + +export interface VerificationMode { + times(count: Number): void + never(): void + once(): void + atLeast(count: Number): void + atMost(count: Number): void +} + +export class MockKit { + constructor() + mockFunc(obj: Object, func: Function): Function + mockObject(obj: Object): Object + verify(methodName: String, argsArray: Array): VerificationMode + ignoreMock(obj: Object, func: Function): void + clear(obj: Object): void + clearAll(): void +} + +export class SysTestKit { + static actionStart(tag: string): void + static actionEnd(tag: string): void + static existKeyword(keyword: string, timeout?: number): boolean +} + +export class Hypium { + static setData(data: {[key: string]: any}): void + static setTimeConfig(systemTime: any) + static hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void +} \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.ets b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.ets new file mode 100644 index 0000000..355d006 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.ets @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Core from './src/main/core'; +import {ConfigService} from './src/main/module/config/configService' +import {DEFAULT, TestType, Size, Level, TAG} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +interface AbilityDelegatorArgs { + bundleName: string; + parameters: Object; + testCaseNames: string; + testRunnerClassName: string; +} + +class Hypium { + static setData(data:Object) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime:Object) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator:Object, abilityDelegatorArguments:AbilityDelegatorArgs, testsuite:Function) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + id: 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + delegator: abilityDelegator, + abilityDelegatorArguments: abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService:ConfigService = core.getDefaultService('config'); + let testParameters:Object = null; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info(`${TAG}parameters:${JSON.stringify(testParameters)}`); + configService.setConfig(testParameters); + + testsuite(); + core.execute(abilityDelegator); + } +} + +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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.js new file mode 100644 index 0000000..affc83b --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/index.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Core from './src/main/core'; +import {DEFAULT, TestType, Size, Level, TAG} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +class Hypium { + static setData(data) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + 'delegator': abilityDelegator, + 'abilityDelegatorArguments': abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService = core.getDefaultService('config'); + + let testParameters = {}; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info(`${TAG}parameters:${JSON.stringify(testParameters)}`); + configService.setConfig(testParameters); + + testsuite(); + core.execute(abilityDelegator); + } +} + +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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/oh-package.json5 b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/oh-package.json5 new file mode 100644 index 0000000..586263c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "@ohos/hypium", + "version": "1.0.9", + "description": "A unit test framework for OpenHarmony application", + "main": "index.js", + "keywords": [], + "author": "huawei", + "license": "Apache-2.0", + "dependencies": { + } +} diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/Constant.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/Constant.js new file mode 100644 index 0000000..13f6849 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/Constant.js @@ -0,0 +1,49 @@ +/* + * 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 TAG = '[Hypium]'; + +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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/core.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/core.js new file mode 100644 index 0000000..cfcb5f1 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/core.js @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SuiteService, SpecService, ExpectService, ReportService} from './service'; +import {ConfigService} from './module/config/configService'; +import {SpecEvent, TaskEvent, SuiteEvent} from './event'; + +/** + * core service for execute testcase. + */ +class Core { + static getInstance() { + if (!this.instance) { + this.instance = new Core(); + } + return this.instance; + } + + constructor() { + this.instance = null; + this.services = { + suite: {}, + spec: {}, + config: {}, + expect: {}, + log: {}, + report: {} + + }; + this.events = { + suite: {}, + spec: {}, + task: {} + }; + } + + addService(name, service) { + let serviceObj = {}; + if (!this.services[name]) { + this.services[name] = serviceObj; + } else { + serviceObj = this.services[name]; + } + serviceObj[service.id] = service; + } + + getDefaultService(name) { + return this.services[name].default; + } + + getServices(name) { + return this.services[name]; + } + + registerEvent(serviceName, event) { + let eventObj = {}; + if (!this.events[serviceName]) { + this.events[serviceName] = eventObj; + } else { + eventObj = this.events[serviceName]; + } + eventObj[event.id] = event; + } + + unRegisterEvent(serviceName, eventID) { + const eventObj = this.events[serviceName]; + if (eventObj) { + delete eventObj[eventID]; + } + } + + subscribeEvent(serviceName, serviceObj) { + const eventObj = this.events[serviceName]; + if (eventObj) { + for (const attr in eventObj) { + eventObj[attr]['subscribeEvent'](serviceObj); + } + } + } + + async fireEvents(serviceName, eventName) { + const eventObj = this.events[serviceName]; + if (!eventObj) { + return; + } + for (const attr in eventObj) { + await eventObj[attr][eventName](); + } + } + + addToGlobal(apis) { + if (typeof globalThis !== 'undefined') { + for (let api in apis) { + globalThis[api] = apis[api]; + } + } + for (const api in apis) { + this[api] = apis[api]; + } + } + + init() { + this.addService('suite', new SuiteService({id: 'default'})); + this.addService('spec', new SpecService({id: 'default'})); + this.addService('expect', new ExpectService({id: 'default'})); + this.addService('report', new ReportService({id: 'default'})); + this.addService('config', new ConfigService({id: 'default'})); + this.registerEvent('task', new TaskEvent({id: 'default', coreContext: this})); + this.registerEvent('suite', new SuiteEvent({id: 'default', coreContext: this})); + this.registerEvent('spec', new SpecEvent({id: 'default', coreContext: this})); + this.subscribeEvent('spec', this.getDefaultService('report')); + this.subscribeEvent('suite', this.getDefaultService('report')); + this.subscribeEvent('task', this.getDefaultService('report')); + const context = this; + for (const key in this.services) { + const serviceObj = this.services[key]; + for (const serviceID in serviceObj) { + const service = serviceObj[serviceID]; + service.init(context); + + if (typeof service.apis !== 'function') { + continue; + } + const apis = service.apis(); + if (apis) { + this.addToGlobal(apis); + } + } + } + } + + execute(abilityDelegator) { + const suiteService = this.getDefaultService('suite'); + const configService = this.getDefaultService('config'); + if (configService['dryRun'] === 'true') { + (async function () { + await suiteService.dryRun(abilityDelegator); + })(); + return; + } + setTimeout(() => { + suiteService.execute(); + }, 10); + } +} + +export default Core; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/event.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/event.js new file mode 100644 index 0000000..1333a1c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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); + } + + async specStart() { + for (const monitor of this.eventMonitors) { + await monitor['specStart'](); + } + } + + async specDone() { + for (const monitor of this.eventMonitors) { + await monitor['specDone'](); + } + } +} + +class SuiteEvent { + constructor(attr) { + this.id = attr.id; + this.suiteContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async suiteStart() { + for (const monitor of this.eventMonitors) { + await monitor['suiteStart'](); + } + } + + async suiteDone() { + for (const monitor of this.eventMonitors) { + await monitor['suiteDone'](); + } + } +} + +class TaskEvent { + constructor(attr) { + this.id = attr.id; + this.coreContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async taskStart() { + for (const monitor of this.eventMonitors) { + await monitor['taskStart'](); + } + } + + async taskDone() { + for (const monitor of this.eventMonitors) { + await monitor['taskDone'](); + } + } + + incorrectFormat() { + for (const monitor of this.eventMonitors) { + monitor['incorrectFormat'](); + } + } +} + +export {SpecEvent, TaskEvent, SuiteEvent}; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/interface.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/interface.js new file mode 100644 index 0000000..40398c8 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/interface.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. + */ + +import Core from './core'; + +const core = Core.getInstance(); + +const describe = function (desc, func) { + return Reflect.has(core, 'describe') ? core.describe(desc, func) : (desc, func) => { }; +}; +const it = function (desc, filter, func) { + return Reflect.has(core, 'it') ? core.it(desc, filter, func) : (desc, filter, func) => { }; +}; +const beforeEach = function (func) { + return Reflect.has(core, 'beforeEach') ? core.beforeEach(func) : (func) => { }; +}; +const afterEach = function (func) { + return Reflect.has(core, 'afterEach') ? core.afterEach(func) : (func) => { }; +}; +const beforeAll = function (func) { + return Reflect.has(core, 'beforeAll') ? core.beforeAll(func) : (func) => { }; +}; +const afterAll = function (func) { + return Reflect.has(core, 'afterAll') ? core.afterAll(func) : (func) => { }; +}; +const expect = function (actualValue) { + return Reflect.has(core, 'expect') ? core.expect(actualValue) : (actualValue) => { }; +}; + +export { + describe, it, beforeAll, beforeEach, afterEach, afterAll, expect +}; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js new file mode 100644 index 0000000..d10d15e --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import assertNull from './assertNull'; +import assertClose from './assertClose'; +import assertContain from './assertContain'; +import assertLess from './assertLess'; +import assertLarger from './assertLarger'; +import assertFail from './assertFail'; +import assertUndefined from './assertUndefined'; +import assertFalse from './assertFalse'; +import assertInstanceOf from './assertInstanceOf'; +import assertThrowError from './assertThrowError'; +import assertLargerOrEqual from './assertLargerOrEqual' +import assertLessOrEqual from './assertLessOrEqual' +import assertNaN from './assertNaN' +import assertNegUnlimited from './assertNegUnlimited' +import assertPosUnlimited from './assertPosUnlimited' +import assertDeepEquals from './deepEquals/assertDeepEquals' +import assertPromiseIsPending from './assertPromiseIsPending'; +import assertPromiseIsRejected from './assertPromiseIsRejected'; +import assertPromiseIsRejectedWith from './assertPromiseIsRejectedWith'; +import assertPromiseIsRejectedWithError from './assertPromiseIsRejectedWithError'; +import assertPromiseIsResolved from './assertPromiseIsResolved'; +import assertPromiseIsResolvedWith from './assertPromiseIsResolvedWith'; +class ExpectExtend { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + extendsMatchers() { + this.matchers.assertNull = assertNull; + this.matchers.assertClose = assertClose; + this.matchers.assertContain = assertContain; + this.matchers.assertLess = assertLess; + this.matchers.assertLarger = assertLarger; + this.matchers.assertFail = assertFail; + this.matchers.assertUndefined = assertUndefined; + this.matchers.assertFalse = assertFalse; + this.matchers.assertInstanceOf = assertInstanceOf; + this.matchers.assertThrowError = assertThrowError; + this.matchers.assertLargerOrEqual = assertLargerOrEqual; + this.matchers.assertLessOrEqual = assertLessOrEqual; + this.matchers.assertNaN = assertNaN; + this.matchers.assertNegUnlimited = assertNegUnlimited; + this.matchers.assertPosUnlimited = assertPosUnlimited; + this.matchers.assertDeepEquals = assertDeepEquals; + this.matchers.assertPromiseIsPending = assertPromiseIsPending; + this.matchers.assertPromiseIsRejected = assertPromiseIsRejected; + this.matchers.assertPromiseIsRejectedWith = assertPromiseIsRejectedWith; + this.matchers.assertPromiseIsRejectedWithError = assertPromiseIsRejectedWithError; + this.matchers.assertPromiseIsResolved = assertPromiseIsResolved; + this.matchers.assertPromiseIsResolvedWith = assertPromiseIsResolvedWith; + } + + init(coreContext) { + this.coreContext = coreContext; + this.extendsMatchers(); + const expectService = this.coreContext.getDefaultService('expect'); + expectService.addMatchers(this.matchers); + } + + apis() { + return { + 'expect': function (actualValue) { + return this.coreContext.getDefaultService('expect').expect(actualValue); + } + }; + } +} + +export default ExpectExtend; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js new file mode 100644 index 0000000..63635be --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js new file mode 100644 index 0000000..7fba0d9 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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: 'expect false, ' + actualValue + ' do not have ' + expect[0] + }; +} + +export default assertContain; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js new file mode 100644 index 0000000..8ab4ac5 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js new file mode 100644 index 0000000..c5008e9 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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: 'expect false, actualValue is ' + actualValue + }; +} + +export default assertFalse; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js new file mode 100644 index 0000000..1e11b93 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js new file mode 100644 index 0000000..a74f4a8 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js new file mode 100644 index 0000000..e847e6c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertLargerOrEqual(actualValue, expected) { + return { + pass: (actualValue) >= expected[0], + message: (actualValue) + ' is not larger than ' + expected[0] + }; +} + +export default assertLargerOrEqual; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js new file mode 100644 index 0000000..17e84b0 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js new file mode 100644 index 0000000..f754f97 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertLessOrEqual(actualValue, expected) { + return { + pass: (actualValue) <= expected[0], + message: (actualValue) + ' is not less than ' + expected[0] + }; +} + +export default assertLessOrEqual; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js new file mode 100644 index 0000000..8d45d6a --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertNaN(actualValue) { + return { + pass: actualValue !== actualValue, + message: 'expect NaN, actualValue is ' + actualValue + }; +} + +export default assertNaN; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js new file mode 100644 index 0000000..ceac555 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function assertNegUnlimited(actualValue) { + return { + pass: actualValue === Number.NEGATIVE_INFINITY, + message: 'Expected actualValue not to be -Infinity. actualValue is,' + actualValue + }; +} + +export default assertNegUnlimited; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js new file mode 100644 index 0000000..53a7bad --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js new file mode 100644 index 0000000..6e68c0e --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function assertPosUnlimited(actualValue) { + return { + pass: actualValue === Number.POSITIVE_INFINITY, + message: 'Expected actualValue is POSITIVE_INFINITY. actualValue is,' + actualValue + }; +} + +export default assertPosUnlimited; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js new file mode 100644 index 0000000..7e2ca2c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsPending(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? {pass: true, message: 'actualValue is isPending'} + : { + pass: false, + message: 'expect isPending, actualValue is resolve' + }; + }, + function () { + return { + pass: false + , message: 'expect isPending, actualValue is reject' + }; + }); +} + +export default assertPromiseIsPending; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js new file mode 100644 index 0000000..eb8e65c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejected(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'expect isRejected, but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function () { + return {pass: true, message: 'actualValue is isRejected'}; + } + ); +} + +export default assertPromiseIsRejected; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js new file mode 100644 index 0000000..48eaf78 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWith(actualPromise, expectedValue) { + + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ('Expected a promise ' + (passed ? 'not ' : '') + + 'to be rejected with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: tips(false) + ' but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + if (JSON.stringify(actualValue) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } else { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } + } + ); +} + +export default assertPromiseIsRejectedWith; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js new file mode 100644 index 0000000..20f236f --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWithError(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'Expected a promise to be rejected but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + return matchError(actualValue, expectedValue); + } + ); + +} + +function matchError(actualValue, expectedValue) { + if (expectedValue.length == 1 && typeof expectedValue[0] === 'function') { + if (expectedValue[0].name === actualValue.__proto__.name) { + return {pass: true, message: 'actual error type is ' + actualValue.name + '.'}; + } + return {pass: false, message: `except error type is ${expectedValue[0].name},but actual is ${actualValue.name}.`}; + } + + if (expectedValue.length == 1 && typeof expectedValue[0] === 'string') { + if (expectedValue[0] === actualValue.message) { + return {pass: true, message: `actual error message is ${actualValue.message}.`}; + } + return {pass: false, message: `except error message ${expectedValue[0]},but actual is ${actualValue.message}.`}; + } + + if (expectedValue.length == 1) { + return {pass: false, message: 'When only one parameter, it should be error type or error message.'}; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name === actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; + } + return {pass: false, message: `except error message is ${expectedValue[1]},but actual is ${actualValue.message}.`}; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name !== actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: false, message: `except error type is ${expectedValue[0].name},but actual is ${actualValue.name}.`}; + } + return {pass: false, message: 'except error type and message are incorrect.'}; + } + if (expectedValue.length > 2) { + return {pass: false, message: 'Up to two parameters are supported.'}; + } +} + +export default assertPromiseIsRejectedWithError; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js new file mode 100644 index 0000000..855426c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolved(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? { + pass: false, + message: 'expect resolve, actualValue is isPending' + } + : {pass: true, message: 'actualValue is isResolved'}; + }, + function (rej) { + return { + pass: false, + message: 'Expected a promise to be resolved but it was ' + + 'rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolved; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js new file mode 100644 index 0000000..d5eb01e --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolvedWith(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ( + 'Expected a promise ' + (passed ? 'not ' : '') + + 'to be resolved with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + if (helper === got) { + return {pass: false, message: 'expect resolve, actualValue is isPending'}; + } + if (JSON.stringify(got) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was resolved with ' + JSON.stringify(got) + '.' + }; + } + return { + pass: false, + message: tips(false) + ' but it was resolved with ' + + JSON.stringify(got) + '.' + }; + }, + function (rej) { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolvedWith; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js new file mode 100644 index 0000000..749cab0 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js new file mode 100644 index 0000000..61f092d --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js new file mode 100644 index 0000000..627fb3b --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class DeepTypeUtils { + static getType_(value) { + return Object.prototype.toString.apply(value); + } + static isA_(typeName, value) { + return this.getType_(value) === '[object ' + typeName + ']'; + } + static isAsymmetricEqualityTester_(obj) { + return obj ? this.isA_('Function', obj.asymmetricMatch) : false; + } + + /** + * 是否是function + * @param value + */ + static isFunction_(value) { + return this.isA_('Function', value); + } + + /** + * 是否是undefined + * @param obj + */ + static isUndefined(obj) { + return obj === void 0; + } + + /** + * 是否是Node + * @param obj + */ + static isDomNode(obj) { + return obj !== null && + typeof obj === 'object' && + typeof obj.nodeType === 'number' && + typeof obj.nodeName === 'string'; + } + + /** + * 是否是promise对象 + * @param obj + */ + static isPromise (obj) { + return !!obj && obj.constructor === Promise; + }; + /** + * 是否是map对象 + * @param obj + */ + static isMap(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Map + ); + } + + /** + * 是否是set对象 + * @param obj 对象 + */ + static isSet(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Set + ); + } + + /** + * 对象是否有key属性 + * @param obj 对象 + * @param key 对象属性名称 + */ + static has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + } + + /** + * 获取对象的自有属性 + * @param obj 对象 + * @param isArray 是否是数组,[object Array] + */ + static keys(obj, isArray) { + const extraKeys = []; + // 获取对象所有属性 + const allKeys = this.getAllKeys(obj); + if (!isArray) { + return allKeys; + } + if (allKeys.length === 0) { + return allKeys; + } + for (const k of allKeys) { + if (typeof k === 'symbol' || !/^[0-9]+$/.test(k)) { + extraKeys.push(k); + } + } + return extraKeys; + } + + /** + * 获取obj对象的所有属性 + * @param obj obj对象 + */ + static getAllKeys(obj) { + const keys = []; + for (let key in obj) { + if(this.has(obj, key)) { + keys.push(key); + } + } + const symbols = Object.getOwnPropertySymbols(obj); + for (const sym of symbols) { + if (obj.propertyIsEnumerable(sym)) { + keys.push(sym); + } + } + return keys; + } + +} +export default DeepTypeUtils; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js new file mode 100644 index 0000000..482e28e --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DeepTypeUtils from './DeepTypeUtils' +function assertDeepEquals(actualValue, expected) { + console.log('actualValue:' + actualValue + ',expected:' + expected[0]); + let result = eq(actualValue, expected[0],[], []) + let msg = logMsg(actualValue, expected[0]); + return { + pass: result, + message: msg + }; +} + +/** + * 获取失败显示日志 + * @param actualValue 实际对象 + * @param expected 期待比较对象 + */ +function logMsg(actualValue, expected) { + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(actualValue); + const bClassName = Object.prototype.toString.call(expected); + let actualMsg; + let expectMsg; + if(aClassName == "[object Function]") { + actualMsg = "actualValue Function" + }else if(aClassName == "[object Promise]") { + actualMsg = "actualValue Promise" + }else if(aClassName == "[object Set]" || aClassName == "[object Map]") { + actualMsg = JSON.stringify(Array.from(actualValue));; + }else if(aClassName == "[object RegExp]") { + actualMsg = JSON.stringify(actualValue.source.replace("\\",""));; + }else if(aClassName == "[object BigInt]") { + actualMsg = actualValue; + } + else{ + actualMsg = JSON.stringify(actualValue); + } + if(bClassName == "[object Function]") { + expectMsg = "expected Function" + }else if(bClassName == "[object Promise]") { + expectMsg = "expected Promise" + }else if(bClassName == "[object Set]" || bClassName == "[object Map]") { + expectMsg = JSON.stringify(Array.from(expected)); + }else if(bClassName == "[object RegExp]") { + expectMsg = JSON.stringify(expected.source.replace("\\",""));; + }else if(bClassName == "[object BigInt]") { + expectMsg = expected; + } + else{ + expectMsg = JSON.stringify(expected); + } + return actualMsg + " is not deep equal " + expectMsg; +} + +function eq(a, b, aStack, bStack) { + let result = true; + console.log('a is:' + a + ',b is:' + b); + const asymmetricResult = asymmetricMatch_(a,b); + if (!DeepTypeUtils.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + + if (a instanceof Error && b instanceof Error) { + result = a.message == b.message; + return result; + } + + if (a === b) { + result = a !== 0 || 1 / a == 1 / b; + return result; + } + + if (a === null || b === null) { + result = a === b; + return result; + } + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(a); + const bClassName = Object.prototype.toString.call(b); + console.log('aClassName is:' + aClassName); + console.log('bClassName is:' + bClassName); + // 不同类型不同对象 + if (aClassName != bClassName) { + return false; + } + // 俩个string对象 + if(aClassName === '[object String]') { + result = a == String(b); + return result; + } + // 俩个Number对象 + if(aClassName === '[object Number]') { + result = a != +a ? b != +b : a === 0 && b === 0 ? 1 / a == 1 / b : a == +b; + return result; + } + + if(aClassName === '[object Date]' || aClassName === '[object Boolean]') { + result = +a == +b; + return result; + } + + // 数组 + if(aClassName === '[object ArrayBuffer]') { + return eq(new Uint8Array(a), new Uint8Array(b), aStack, bStack); + } + + // 正则表达式 + if(aClassName === '[object RegExp]') { + return ( + a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase + ); + } + + if (typeof a != 'object' || typeof b != 'object') { + return false; + } + + const aIsDomNode = DeepTypeUtils.isDomNode(a); + const bIsDomNode = DeepTypeUtils.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + result = a.isEqualNode(b); + return result; + } + if (aIsDomNode || bIsDomNode) { + return false; + } + const aIsPromise = DeepTypeUtils.isPromise(a); + const bIsPromise = DeepTypeUtils.isPromise(b); + if (aIsPromise && bIsPromise) { + return a === b; + } + let length = aStack.length; + while (length--) { + if (aStack[length] == a) { + return bStack[length] == b; + } + } + aStack.push(a); + bStack.push(b); + let size = 0; + + // 都是数组 + if(aClassName == '[object Array]') { + const aLength = a.length; + const bLength = b.length; + if (aLength !== bLength) { + // 数组长度不同,不是同一个对象 + return false; + } + for (let i = 0; i < aLength || i < bLength; i++) { + // 递归每一个元素是否相同 + result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack) && result; + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isMap(a) && DeepTypeUtils.isMap(b)) { + if (a.size != b.size) { + return false; + } + const keysA = []; + const keysB = []; + a.forEach(function(valueA, keyA) { + keysA.push(keyA); + }); + b.forEach(function(valueB, keyB) { + keysB.push(keyB); + }); + const mapKeys = [keysA, keysB]; + const cmpKeys = [keysB, keysA]; + for (let i = 0; result && i < mapKeys.length; i++) { + const mapIter = mapKeys[i]; + const cmpIter = cmpKeys[i]; + + for (let j = 0; result && j < mapIter.length; j++) { + const mapKey = mapIter[j]; + const cmpKey = cmpIter[j]; + const mapValueA = a.get(mapKey); + let mapValueB; + if ( + DeepTypeUtils.isAsymmetricEqualityTester_(mapKey) || + (DeepTypeUtils.isAsymmetricEqualityTester_(cmpKey) && + eq(mapKey, cmpKey)) + ) { + mapValueB = b.get(cmpKey); + } else { + mapValueB = b.get(mapKey); + } + result = eq(mapValueA, mapValueB, aStack, bStack); + } + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isSet(a) && DeepTypeUtils.isSet(b)) { + if (a.size != b.size) { + return false; + } + const valuesA = []; + a.forEach(function(valueA) { + valuesA.push(valueA); + }); + const valuesB = []; + b.forEach(function(valueB) { + valuesB.push(valueB); + }); + const setPairs = [[valuesA, valuesB], [valuesB, valuesA]]; + const stackPairs = [[aStack, bStack], [bStack, aStack]]; + for (let i = 0; result && i < setPairs.length; i++) { + const baseValues = setPairs[i][0]; + const otherValues = setPairs[i][1]; + const baseStack = stackPairs[i][0]; + const otherStack = stackPairs[i][1]; + for (const baseValue of baseValues) { + let found = false; + for (let j = 0; !found && j < otherValues.length; j++) { + const otherValue = otherValues[j]; + const prevStackSize = baseStack.length; + // 深度比较对象 + found = eq(baseValue, otherValue, baseStack, otherStack); + if (!found && prevStackSize !== baseStack.length) { + baseStack.splice(prevStackSize); + otherStack.splice(prevStackSize); + } + } + result = result && found; + } + } + if (!result) { + return false; + } + } else { + const aCtor = a.constructor, + bCtor = b.constructor; + if ( + aCtor !== bCtor && + DeepTypeUtils.isFunction_(aCtor) && + DeepTypeUtils.isFunction_(bCtor) && + a instanceof aCtor && + b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor) + ) { + return false; + } + } + + // 获取对象所有的属性集合 + const aKeys = DeepTypeUtils.keys(a, aClassName == '[object Array]'); + size = aKeys.length; + + // 俩个对象属性长度不一致, 俩对象不相同 + if (DeepTypeUtils.keys(b, bClassName == '[object Array]').length !== size) { + return false; + } + + // 俩对象属性数量相同, 递归比较每个属性值得值 + for (const key of aKeys) { + console.log('key is:' + key); + // b 没有 key 属性 + if(!DeepTypeUtils.has(b, key)) { + result = false; + continue; + } + if (!eq(a[key], b[key], aStack, bStack)) { + result = false; + } + } + if (!result) { + return false; + } + aStack.pop(); + bStack.pop(); + return result; +} + +function asymmetricMatch_(a, b) { + const asymmetricA = DeepTypeUtils.isAsymmetricEqualityTester_(a); + const asymmetricB = DeepTypeUtils.isAsymmetricEqualityTester_(b); + + if (asymmetricA === asymmetricB) { + return undefined; + } + +} + +/** + * 获取对象的自有属性 + * + * @param obj 对象 + * @param isArray 是否是一个数组 + */ +function keys(obj, isArray) { + const keys = []; + +} + +export default assertDeepEquals; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js new file mode 100644 index 0000000..015ab19 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js new file mode 100644 index 0000000..639dffc --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + return ObjectUtils.get(specItem, PARAMS_KEY, specParams); + } + } + } + } + return specParams; + } + + getSuiteParams() { + let suiteParams = {}; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + suiteParams = Object.assign({}, suiteParams, ObjectUtils.get(suiteItem, PARAMS_KEY, suiteParams)); + } + } + return suiteParams; + } + + getSpecStress(specDesc) { + let stress = 1; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + let tempStress = ObjectUtils.get(specItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + } + } + return stress; + } + + getSuiteStress(suiteDesc) { + let stress = 1; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + return stress; + } +} + +export default DataDriver; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/Filter.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/Filter.js new file mode 100644 index 0000000..0ca3b4f --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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.split(',').some(item => item == (this.suiteName + '#' + this.itName)); + } +} + +class SuiteAndItNameFilter { + constructor(suiteName, itName, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + } + + filterSuite() { + return !this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + } + + filterIt() { + return !this.params.split(',').map(item => item == this.itName).reduce((pre, cur) => pre || cur, false); + } +} + + +class TestTypesFilter { + constructor(suiteName, itName, fi, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + this.fi = fi; + } + + filterIt() { + return !((this.params === (this.fi & this.params)) || this.fi === 0); + } +} + +export {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter}; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/configService.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/configService.js new file mode 100644 index 0000000..94f4a76 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/config/configService.js @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter} from './Filter'; +import {TAG} from '../../Constant'; +const STRESS_RULE = /^[1-9]\d*$/; + +class ConfigService { + constructor(attr) { + this.id = attr.id; + this.supportAsync = false; + this.random = false; + this.filterValid = []; + this.filter = 0; + this.flag = false; + this.suite = null; + this.itName = null; + this.testType = null; + this.level = null; + this.size = null; + this.class = null; + this.notClass = null; + this.timeout = null; + // 遇错即停模式配置 + this.breakOnError = false; + // 压力测试配置 + this.stress = null; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + isNormalInteger(str) { + const n = Math.floor(Number(str)); + return n !== Infinity && String(n) === String(str) && n >= 0; + } + + getStress() { + if (this.stress === undefined || this.stress === '' || this.stress === null) { + return 1; + } + return !this.stress.match(STRESS_RULE) ? 1 : Number.parseInt(this.stress); + } + + basicParamValidCheck(params) { + let size = params.size; + if (size !== undefined && size !== '' && size !== null) { + let sizeArray = ['small', 'medium', 'large']; + if (sizeArray.indexOf(size) === -1) { + this.filterValid.push('size:' + size); + } + } + let level = params.level; + if (level !== undefined && level !== '' && level !== null) { + let levelArray = ['0', '1', '2', '3', '4']; + if (levelArray.indexOf(level) === -1) { + this.filterValid.push('level:' + level); + } + } + let testType = params.testType; + if (testType !== undefined && testType !== '' && testType !== null) { + let testTypeArray = ['function', 'performance', 'power', 'reliability', 'security', + 'global', 'compatibility', 'user', 'standard', 'safety', 'resilience']; + if (testTypeArray.indexOf(testType) === -1) { + this.filterValid.push('testType:' + testType); + } + } + } + + filterParamValidCheck(params) { + let timeout = params.timeout; + if (timeout !== undefined && timeout !== '' && timeout !== null) { + if (!this.isNormalInteger(timeout)) { + this.filterValid.push('timeout:' + timeout); + } + } + + let paramKeys = ['dryRun', 'random', 'breakOnError', 'coverage']; + for (const key of paramKeys) { + if (params[key] !== undefined && params[key] !== 'true' && params[key] !== 'false') { + this.filterValid.push(`${key}:${params[key]}`); + } + } + + // 压力测试参数验证,正整数 + if (params.stress !== undefined && params.stress !== '' && params.stress !== null) { + if (!params.stress.match(STRESS_RULE)) { + this.filterValid.push('stress:' + params.stress); + } + } + + let nameRule = /^[A-Za-z]{1}[\w#,.]*$/; + let paramClassKeys = ['class', 'notClass']; + for (const key of paramClassKeys) { + if (params[key] !== undefined && params[key] !== '' && params[key] !== null) { + let classArray = params[key].split(','); + classArray.forEach(item => !item.match(nameRule) ? this.filterValid.push(`${key}:${params[key]}`) : null); + } + } + } + + setConfig(params) { + this.basicParamValidCheck(params); + this.filterParamValidCheck(params); + try { + this.class = params.class; + this.notClass = params.notClass; + this.flag = params.flag || {flag: false}; + this.suite = params.suite; + this.itName = params.itName; + this.filter = params.filter; + this.testType = params.testType; + this.level = params.level; + this.size = params.size; + this.timeout = params.timeout; + this.dryRun = params.dryRun; + this.breakOnError = params.breakOnError; + this.random = params.random === 'true' ? true : false; + this.stress = params.stress; + this.coverage = params.coverage; + this.filterParam = { + testType: { + 'function': 1, + 'performance': 1 << 1, + 'power': 1 << 2, + 'reliability': 1 << 3, + 'security': 1 << 4, + 'global': 1 << 5, + 'compatibility': 1 << 6, + 'user': 1 << 7, + 'standard': 1 << 8, + 'safety': 1 << 9, + 'resilience': 1 << 10, + }, + level: { + '0': 1 << 24, + '1': 1 << 25, + '2': 1 << 26, + '3': 1 << 27, + '4': 1 << 28, + }, + size: { + 'small': 1 << 16, + 'medium': 1 << 17, + 'large': 1 << 18, + } + }; + this.parseParams(); + } catch (err) { + console.info(`${TAG}setConfig error: ${err.message}`); + } + } + + parseParams() { + if (this.filter != null) { + return; + } + let testTypeFilter = 0; + let sizeFilter = 0; + let levelFilter = 0; + if (this.testType != null) { + testTypeFilter = this.testType.split(',') + .map(item => this.filterParam.testType[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.level != null) { + levelFilter = this.level.split(',') + .map(item => this.filterParam.level[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.size != null) { + sizeFilter = this.size.split(',') + .map(item => this.filterParam.size[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + this.filter = testTypeFilter | sizeFilter | levelFilter; + console.info(`${TAG}filter params:${this.filter}`); + } + + isCurrentSuite(description) { + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + let suiteArray = this.suite.split(','); + return suiteArray.indexOf(description) !== -1; + } + return false; + } + + filterSuite(currentSuiteName) { + let filterArray = []; + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, '', this.suite)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, '', this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, '', this.notClass)); + } + + let result = filterArray.map(item => item.filterSuite()).reduce((pre, cur) => pre || cur, false); + return result; + } + + filterDesc(currentSuiteName, desc, fi, coreContext) { + let filterArray = []; + if (this.itName !== undefined && this.itName !== '' && this.itName !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, desc, this.itName)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, desc, this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, desc, this.notClass)); + } + if (typeof (this.filter) !== 'undefined' && this.filter !== 0 && fi !== 0) { + filterArray.push(new TestTypesFilter('', '', fi, this.filter)); + } + let result = filterArray.map(item => item.filterIt()).reduce((pre, cur) => pre || cur, false); + return result; + } + + isRandom() { + return this.random || false; + } + + isBreakOnError() { + return this.breakOnError !== true ? false : true; + } + + setSupportAsync(value) { + this.supportAsync = value; + } + + isSupportAsync() { + return this.supportAsync; + } + + translateParams(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = {}; + for (const key in parameters) { + if (keySet.has(key)) { + var newKey = key.replace("-s ", ""); + targetParams[newKey] = parameters[key]; + } + } + return targetParams; + } + translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key]; + } + } + return targetParams.trim(); + } + + execute() { + } +} + +export { + ConfigService +}; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js new file mode 100644 index 0000000..632a682 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "../kit/SysTestKit"; + +export async function collectCoverageData() { + if (globalThis.__coverage__ === undefined) { + return; + } + const strJson = JSON.stringify(globalThis.__coverage__); + const strLen = strJson.length; + const maxLen = 500; + const maxCount = Math.floor(strLen / maxLen); + const OHOS_REPORT_COVERAGE_DATA = 'OHOS_REPORT_COVERAGE_DATA:'; + for (let count = 0; count <= maxCount; count++) { + console.info(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); + await SysTestKit.print(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); + } +} \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js new file mode 100644 index 0000000..65d063c --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {TAG} from '../../Constant'; + +export default class SysTestKit { + + static delegator = null; + static systemTime = null; + + constructor() { + this.id = 'sysTestKit'; + this.index = 0; + } + + static actionStart(tag) { + console.info(`${TAG}${JSON.stringify(tag)}`); + var message = '\n' + 'OHOS_REPORT_ACTIONSTART: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(`${TAG}${JSON.stringify(tag)} actionStart print success`); + } + + static actionEnd(tag) { + console.info(`${TAG}${JSON.stringify(tag)}`); + var message = '\n' + 'OHOS_REPORT_ACTIONEND: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(`${TAG}${JSON.stringify(tag)} actionEnd print success`); + } + + static async existKeyword(keyword, timeout) { + let reg = new RegExp(/^[a-zA-Z0-9]{1,}$/); + if (!reg.test(keyword)) { + throw new Error('keyword must contain more than one string, and only letters and numbers are supported.'); + } + timeout = timeout || 4; + + let searchResult = false; + let cmd = 'hilog -x | grep -i \'' + keyword + '\' | wc -l'; + await executePromise(cmd, timeout).then((data) => { + searchResult = data; + }); + return searchResult; + } + static async print(message) { + if ('printSync' in SysTestKit.delegator) { + console.debug(`${TAG}printSync called ...`); + SysTestKit.delegator.printSync(message); + } else { + await SysTestKit.delegator.print(message); + } + } + + static async getRealTime() { + let currentTime = new Date().getTime(); + if (SysTestKit.systemTime !== null && SysTestKit.systemTime !== undefined) { + await SysTestKit.systemTime.getRealTime().then((time) => { + console.info(`${TAG}systemTime.getRealTime success data: ${JSON.stringify(time)}`); + currentTime = time; + }).catch((error) => { + console.error(`${TAG}failed to systemTime.getRealTime because ${JSON.stringify(error)}`); + }); + } + return currentTime; + } +} + +function executePromise(cmd, timeout) { + return new Promise((resolve, reject) => { + SysTestKit.delegator.executeShellCommand(cmd, timeout, + (error, data) => { + console.info(`${TAG}existKeyword CallBack: err : ${JSON.stringify(error)}`); + console.info(`${TAG}existKeyword CallBack: data : ${JSON.stringify(data)}`); + resolve(parseInt(data.stdResult) > 3 ? true : false); + }); + }); +} \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js new file mode 100644 index 0000000..6a9d7aa --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js new file mode 100644 index 0000000..c6a866a --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js new file mode 100644 index 0000000..1bd83be --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 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 = new Map(); + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + init() { + this.reset(); + } + + reset() { + this.mFunctions = []; + this.stubs = {}; + this.recordCalls = {}; + this.currentSetKey = new Map(); + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + clearAll() { + this.reset(); + var props = Object.keys(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + + var props = Object.getOwnPropertyNames(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + for (var key in this) { + delete this[key]; + } + } + + clear(obj) { + if (!obj) throw Error("Please enter an object to be cleaned"); + if (typeof (obj) != 'object') throw new Error('Not a object'); + this.recordMockedMethod.forEach(function (value, key, map) { + if (key) { + obj[key] = value; + } + }); + } + + ignoreMock(obj, method) { + if (typeof (obj) != 'object') throw new Error('Not a object'); + if (typeof (method) != 'function') throw new Error('Not a function'); + let og = this.recordMockedMethod.get(method.propName); + if (og) { + obj[method.propName] = og; + this.recordMockedMethod.set(method.propName, undefined); + } + } + + extend(dest, source) { + dest["stub"] = source["stub"]; + dest["afterReturn"] = source["afterReturn"]; + dest["afterReturnNothing"] = source["afterReturnNothing"]; + dest["afterAction"] = source["afterAction"]; + dest["afterThrow"] = source["afterThrow"]; + dest["stubMockedCall"] = source["stubMockedCall"]; + dest["clear"] = source["clear"]; + return dest; + } + + stubApply(f, params, returnInfo) { + let values = this.stubs.get(f); + if (!values) { + values = new Map(); + } + let key = params[0]; + if (typeof key == "undefined") { + key = "anonymous-mock-" + f.propName; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheStubKey(key)) { + key = matcher.matcheStubKey(key); + if (key) { + this.currentSetKey.set(f, key); + } + } + values.set(key, returnInfo); + this.stubs.set(f, values); + } + + getReturnInfo(f, params) { + let values = this.stubs.get(f); + if (!values) { + return undefined; + } + let retrunKet = params[0]; + if (typeof retrunKet == "undefined") { + retrunKet = "anonymous-mock-" + f.propName; + } + let stubSetKey = this.currentSetKey.get(f); + + if (stubSetKey && (typeof (retrunKet) != "undefined")) { + retrunKet = stubSetKey; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheReturnKey(params[0], undefined, stubSetKey) && matcher.matcheReturnKey(params[0], undefined, stubSetKey) != stubSetKey) { + retrunKet = params[0]; + } + + values.forEach(function (value, key, map) { + if (ArgumentMatchers.isRegExp(key) && matcher.matcheReturnKey(params[0], key)) { + retrunKet = key; + } + }); + + return values.get(retrunKet); + } + + findName(obj, value) { + let properties = this.findProperties(obj); + let name = null; + properties.filter(item => (item !== 'caller' && item !== 'arguments')).forEach( + function (va1, idx, array) { + if (obj[va1] === value) { + name = va1; + } + } + ); + return name; + } + + isFunctionFromPrototype(f, container, propName) { + if (container.constructor != Object && container.constructor.prototype !== container) { + return container.constructor.prototype[propName] === f; + } + return false; + } + + findProperties(obj, ...arg) { + function getProperty(new_obj) { + if (new_obj.__proto__ === null) { + return []; + } + let properties = Object.getOwnPropertyNames(new_obj); + return [...properties, ...getProperty(new_obj.__proto__)]; + } + return getProperty(obj); + } + + recordMethodCall(originalMethod, args) { + Function.prototype.getName = function () { + return this.name || this.toString().match(/function\s*([^(]*)\(/)[1]; + }; + let name = originalMethod.getName(); + let arglistString = name + '(' + Array.from(args).toString() + ')'; + let records = this.recordCalls.get(arglistString); + if (!records) { + records = 0; + } + records++; + this.recordCalls.set(arglistString, records); + } + + mockFunc(originalObject, originalMethod) { + let tmp = this; + this.originalMethod = originalMethod; + let f = function () { + let args = arguments; + let action = tmp.getReturnInfo(f, args); + if (originalMethod) { + tmp.recordMethodCall(originalMethod, args); + } + if (action) { + return action.apply(this, args); + } + }; + + f.container = null || originalObject; + f.original = originalMethod || null; + + if (originalObject && originalMethod) { + if (typeof (originalMethod) != 'function') throw new Error('Not a function'); + var name = this.findName(originalObject, originalMethod); + originalObject[name] = f; + this.recordMockedMethod.set(name, originalMethod); + f.propName = name; + f.originalFromPrototype = this.isFunctionFromPrototype(f.original, originalObject, f.propName); + } + f.mocker = this; + this.mFunctions.push(f); + this.extend(f, new ExtendInterface(this)); + return f; + } + + verify(methodName, argsArray) { + if (!methodName) { + throw Error("not a function name"); + } + let a = this.recordCalls.get(methodName + '(' + argsArray.toString() + ')'); + return new VerificationMode(a ? a : 0); + } + + mockObject(object) { + if (!object || typeof object === "string") { + throw Error(`this ${object} cannot be mocked`); + } + const _this = this; + let mockedObject = {}; + let keys = Reflect.ownKeys(object); + keys.filter(key => (typeof Reflect.get(object, key)) === 'function') + .forEach(key => { + mockedObject[key] = object[key]; + mockedObject[key] = _this.mockFunc(mockedObject, mockedObject[key]); + }); + return mockedObject; + } +} + +function ifMockedFunction(f) { + if (Object.prototype.toString.call(f) != "[object Function]" && + Object.prototype.toString.call(f) != "[object AsyncFunction]") { + throw Error("not a function"); + } + if (!f.stub) { + throw Error("not a mock function"); + } + return true; +} + +function when(f) { + if (ifMockedFunction(f)) { + return f.stub.bind(f); + } +} + +export {MockKit, when}; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js new file mode 100644 index 0000000..28eda2b --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {expect} from '../../interface'; + +class VerificationMode { + constructor(times) { + this.doTimes = times; + } + + times(count) { + expect(count).assertEqual(this.doTimes); + } + + never() { + console.log(this.doTimes); + expect(0).assertEqual(this.doTimes); + } + + once() { + expect(1).assertEqual(this.doTimes); + } + + atLeast(count) { + if (count > this.doTimes) { + throw Error('failed ' + count + ' greater than the actual execution times of method'); + } + } + + atMost(count) { + if (count < this.doTimes) { + throw Error('failed ' + count + ' less than the actual execution times of method'); + } + } +} + +export default VerificationMode; \ No newline at end of file diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js new file mode 100644 index 0000000..f648b11 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "../kit/SysTestKit"; +import {collectCoverageData} from '../coverage/coverageCollect'; +import {TAG} from '../../Constant'; + +class OhReport { + constructor(attr) { + this.delegator = attr.delegator; + this.abilityDelegatorArguments = attr.abilityDelegatorArguments; + this.id = 'report'; + this.index = 0; + this.duration = 0; + } + + init(coreContext) { + this.coreContext = coreContext; + this.suiteService = this.coreContext.getDefaultService('suite'); + this.specService = this.coreContext.getDefaultService('spec'); + } + + taskStart() { + } + + async taskDone() { + if (this.abilityDelegatorArguments !== null) { + this.taskDoneTime = new Date().getTime(); + let summary = this.suiteService.getSummary(); + const configService = this.coreContext.getDefaultService('config'); + if (configService['coverage'] === 'true') { + await collectCoverageData(); + } + let message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure; + message += ', Error: ' + summary.error; + message += ', Pass: ' + summary.pass; + message += ', Ignore: ' + summary.ignore; + message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n'; + let isHasError = summary.failure > 0 || summary.error > 0; + let config = this.coreContext.getDefaultService('config'); + if (config.isBreakOnError() && isHasError) { + // 未执行全部说明 + message += '\n' + 'OHOS_REPORT_RESULT: breakOnError model, Stopping whole test suite if one specific test case failed or error' + '\n'; + } + message += 'OHOS_REPORT_STATUS: taskconsuming=' + summary.duration + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + } + console.info(`${TAG}report print success`); + this.delegator.finishTest('your test finished!!!', 0, () => { }); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + var value = this.coreContext.getDefaultService('config').filterValid; + var message = 'this param ' + value.join(',') + ' is invalid' + '\n'; + this.delegator.finishTest(message, 0, () => { + }); + } + } + + async suiteStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_SUM: ' + this.suiteService.getCurrentRunningSuite().getSpecsNum(); + message += '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.suiteService.getCurrentRunningSuite().description} suiteStart print success`); + } + } + + async suiteDone() { + if (this.abilityDelegatorArguments !== null) { + const currentRunningSuite = this.suiteService.getCurrentRunningSuite(); + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: suiteconsuming=' + this.suiteService.getCurrentRunningSuite().duration; + if (currentRunningSuite.hookError) { + message += '\n' + `OHOS_REPORT_STATUS: ${currentRunningSuite.hookError.message}`; + } + message += '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.suiteService.getCurrentRunningSuite().description} suiteDone print success`); + } + } + + async specStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.specService.currentRunningSpec.description} specStart start print success`); + } + } + + async specDone() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + let errorMsg = ''; + if (this.specService.currentRunningSpec.error) { + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -1' + '\n'; + } else if (this.specService.currentRunningSpec) { + if (this.specService.currentRunningSpec.fail) { + errorMsg = this.specService.currentRunningSpec.fail?.message; + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + errorMsg; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + errorMsg + '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -2' + '\n'; + } else { + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 0' + '\n'; + } + } else { + message += '\n'; + } + message += 'OHOS_REPORT_STATUS: consuming=' + this.specService.currentRunningSpec.duration + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.specService.currentRunningSpec.description} specDone end print success`); + } + } +} + +export default OhReport; diff --git a/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js new file mode 100644 index 0000000..852fbcd --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/service.js b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/service.js new file mode 100644 index 0000000..55d04a8 --- /dev/null +++ b/oh_modules/.ohpm/@ohos+hypium@1.0.9/oh_modules/@ohos/hypium/src/main/service.js @@ -0,0 +1,966 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "./module/kit/SysTestKit"; +import {TAG} from './Constant'; + +class AssertException extends Error { + constructor(message) { + super(); + this.name = "AssertException"; + this.message = message; + } +} + +function getFuncWithArgsZero(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + try { + await func(); + } catch (err) { + reject(err); + } + timer !== null ? clearTimeout(timer) : null; + resolve(); + }); +} + +function getFuncWithArgsOne(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout);; + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function getFuncWithArgsTwo(func, timeout, paramItem, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done, paramItem); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function processFunc(coreContext, func) { + let argNames = ((func || '').toString() + .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '') + .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2] + .split(',') // split parameters + .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim())) + .filter(String); + let funcLen = func.length; + let processedFunc; + const config = coreContext.getDefaultService('config'); + config.setSupportAsync(true); + const timeout = + (config.timeout === undefined ? 5000 : config.timeout); + const isStressTest = (coreContext.getServices('dataDriver') !== undefined || config.getStress() > 1); + switch (funcLen) { + case 0: { + processedFunc = function () { + return getFuncWithArgsZero(func, timeout, isStressTest); + }; + break; + } + case 1: { + if (argNames[0] === 'data') { + processedFunc = function (paramItem) { + func(paramItem); + }; + } else { + processedFunc = function () { + return getFuncWithArgsOne(func, timeout, isStressTest); + }; + } + break; + } + default: { + processedFunc = function (paramItem) { + return getFuncWithArgsTwo(func, timeout, paramItem, isStressTest); + }; + break; + } + } + return processedFunc; +} + +function secureRandomNumber() { + return crypto.randomBytes(8).readUInt32LE() / 0xffffffff; +} + +class SuiteService { + constructor(attr) { + this.id = attr.id; + this.rootSuite = new SuiteService.Suite({}); + this.currentRunningSuite = this.rootSuite; + this.suitesStack = [this.rootSuite]; + } + + describe(desc, func) { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterSuite(desc)) { + console.info(`${TAG}filter suite : ${desc}`); + return; + } + const suite = new SuiteService.Suite({description: desc}); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc); + for (let i = 1; i < suiteStress; i++) { + this.currentRunningSuite.childSuites.push(suite); + } + } + this.currentRunningSuite.childSuites.push(suite); + this.currentRunningSuite = suite; + this.suitesStack.push(suite); + func.call(); + let childSuite = this.suitesStack.pop(); + if (this.suitesStack.length === 0) { + this.currentRunningSuite = childSuite; + this.suitesStack.push(childSuite); + } + if (this.suitesStack.length > 1) { + this.currentRunningSuite = this.suitesStack.pop(); + } else { + this.currentRunningSuite = this.suitesStack.pop(); + this.suitesStack.push(this.currentRunningSuite); + } + } + + beforeAll(func) { + this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func)); + } + + beforeEach(func) { + this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func)); + } + + afterAll(func) { + this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func)); + } + + afterEach(func) { + this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func)); + } + + getCurrentRunningSuite() { + return this.currentRunningSuite; + } + + setCurrentRunningSuite(suite) { + this.currentRunningSuite = suite; + } + + traversalResults(suite, obj, breakOnError) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + for (const itItem of suite.specs) { + obj.total++; + if (breakOnError && (obj.error > 0 || obj.failure > 0)) { // breakOnError模式 + continue; + } + if (itItem.error) { + obj.error++; + } else if (itItem.fail) { + obj.failure++; + } else if (itItem.pass === true) { + obj.pass++; + } + } + } + + obj.duration += suite.duration; + + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + this.traversalResults(suiteItem, obj, breakOnError); + } + } + } + + async setSuiteResults(suite, error, coreContext) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + const specService = coreContext.getDefaultService('spec'); + for (const specItem of suite.specs) { + specService.setCurrentRunningSpec(specItem); + if (error instanceof AssertException) { + specItem.fail = error; + } else { + specItem.error = error; + } + await coreContext.fireEvents('spec', 'specStart', specItem); + await coreContext.fireEvents('spec', 'specDone', specItem); + } + } + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + await this.setSuiteResults(suiteItem, error, coreContext); + } + } + } + + getSummary() { + let suiteService = this.coreContext.getDefaultService('suite'); + let rootSuite = suiteService.rootSuite; + const specService = this.coreContext.getDefaultService('spec'); + const configService = this.coreContext.getDefaultService('config'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + let isBreaKOnError = breakOnError && isError; + let obj = {total: 0, failure: 0, error: 0, pass: 0, ignore: 0, duration: 0}; + for (const suiteItem of rootSuite.childSuites) { + this.traversalResults(suiteItem, obj, isBreaKOnError); + } + obj.ignore = obj.total - obj.pass - obj.failure - obj.error; + return obj; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + traversalSuites(suite, obj, configService) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return []; + } + if (suite.specs.length > 0) { + let itArray = []; + for (const itItem of suite['specs']) { + if (!configService.filterDesc(suite.description, itItem.description, itItem.fi, null)) { + itArray.push({'itName': itItem.description}); + } + } + obj[suite.description] = itArray; + } + + if (suite.childSuites.length > 0) { + let suiteArray = []; + for (const suiteItem of suite.childSuites) { + let suiteObj = {}; + this.traversalSuites(suiteItem, suiteObj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suiteArray.push(suiteObj); + } + } + obj.suites = suiteArray; + } + } + + async dryRun(abilityDelegator) { + const configService = this.coreContext.getDefaultService('config'); + let testSuitesObj = {}; + let suitesArray = []; + for (const suiteItem of this.rootSuite.childSuites) { + let obj = {}; + this.traversalSuites(suiteItem, obj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suitesArray.push(obj); + } + } + testSuitesObj['suites'] = suitesArray; + + let strJson = JSON.stringify(testSuitesObj); + let strLen = strJson.length; + let maxLen = 500; + let maxCount = Math.floor(strLen / maxLen); + + for (let count = 0; count <= maxCount; count++) { + await SysTestKit.print(strJson.substring(count * maxLen, (count + 1) * maxLen)); + } + console.info(`${TAG}dryRun print success`); + abilityDelegator.finishTest('dry run finished!!!', 0, () => { }); + } + + execute() { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterValid.length !== 0) { + this.coreContext.fireEvents('task', 'incorrectFormat'); + return; + } + + if (configService.isRandom() && this.rootSuite.childSuites.length > 0) { + this.rootSuite.childSuites.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + this.currentRunningSuite = this.rootSuite.childSuites[0]; + } + + if (configService.isSupportAsync()) { + let asyncExecute = async () => { + await this.coreContext.fireEvents('task', 'taskStart'); + await this.rootSuite.asyncRun(this.coreContext); + }; + asyncExecute().then(async () => { + await this.coreContext.fireEvents('task', 'taskDone'); + }); + } else { + this.coreContext.fireEvents('task', 'taskStart'); + this.rootSuite.run(this.coreContext); + this.coreContext.fireEvents('task', 'taskDone'); + } + } + + apis() { + const _this = this; + return { + describe: function (desc, func) { + return _this.describe(desc, func); + }, + beforeAll: function (func) { + return _this.beforeAll(func); + }, + beforeEach: function (func) { + return _this.beforeEach(func); + }, + afterAll: function (func) { + return _this.afterAll(func); + }, + afterEach: function (func) { + return _this.afterEach(func); + } + }; + } +} + +SuiteService.Suite = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.childSuites = []; + this.specs = []; + this.beforeAll = []; + this.afterAll = []; + this.beforeEach = []; + this.afterEach = []; + this.duration = 0; + this.hookError = null; + } + + pushSpec(spec) { + this.specs.push(spec); + } + + removeSpec(desc) { + this.specs = this.specs.filter((item, index) => { + return item.description !== desc; + }); + } + + getSpecsNum() { + return this.specs.length; + } + + isRun(coreContext) { + const configService = coreContext.getDefaultService('config'); + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + return breakOnError && isError; + } + + run(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteStart', this); + } + this.runHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + for (let spec in this.specs) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + this.runHookFunc('beforeEach'); + spec.run(coreContext); + this.runHookFunc('afterEach'); + } + } + if (this.childSuites.length > 0) { + for (let suite in this.childSuites) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + suite.run(coreContext); + suiteService.setCurrentRunningSuite(suite); + } + } + this.runHookFunc('afterAll'); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteDone'); + } + } + + async asyncRunSpecs(coreContext) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + const specService = coreContext.getDefaultService('spec'); + for (let specItem of this.specs) { + specService.setCurrentRunningSpec(specItem); + // 遇错即停模式,发现用例有问题,直接返回,不在执行后面的it + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log("break description :" + this.description); + break; + } + await coreContext.fireEvents('spec', 'specStart', specItem); + try { + await this.runAsyncHookFunc('beforeEach'); + await specItem.asyncRun(coreContext); + await this.runAsyncHookFunc('afterEach'); + } catch (e) { + console.error(`${TAG}${e?.stack}`); + if (e instanceof AssertException) { + specItem.fail = e; + } else { + specItem.error = e; + } + specService.setStatus(true); + } + specItem.setResult(); + await coreContext.fireEvents('spec', 'specDone', specItem); + specService.setCurrentRunningSpec(null); + } + } + + async asyncRunChildSuites(coreContext) { + for (let i = 0; i < this.childSuites.length; i++) { + // 遇错即停模式, 发现用例有问题,直接返回,不在执行后面的description + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log(`${TAG}break description : ${this.description}`); + break; + } + await this.childSuites[i].asyncRun(coreContext); + } + } + + async asyncRun(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + + suiteService.setCurrentRunningSuite(this); + suiteService.suitesStack.push(this); + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteStart', this); + } + + try { + await this.runAsyncHookFunc('beforeAll'); + } catch (error) { + console.error(`${TAG}${error?.stack}`); + this.hookError = error; + } + + if (this.hookError !== null) { + specService.setStatus(true); + await suiteService.setSuiteResults(this, this.hookError, coreContext); + } + + if (this.specs.length > 0 && this.hookError === null) { + await this.asyncRunSpecs(coreContext); + } + + if (this.childSuites.length > 0 && this.hookError === null) { + await this.asyncRunChildSuites(coreContext); + } + + try { + await this.runAsyncHookFunc('afterAll'); + } catch (error) { + console.error(`${TAG}${error?.stack}`); + this.hookError = error; + specService.setStatus(true); + } + + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteDone'); + let childSuite = suiteService.suitesStack.pop(); + if (suiteService.suitesStack.length === 0) { + suiteService.suitesStack.push(childSuite); + } + if (suiteService.suitesStack.length > 1) { + suiteService.setCurrentRunningSuite(suiteService.suitesStack.pop()); + } else { + let currentRunningSuite = suiteService.suitesStack.pop(); + suiteService.setCurrentRunningSuite(currentRunningSuite); + suiteService.suitesStack.push(currentRunningSuite); + } + } + } + + runHookFunc(hookName) { + if (this[hookName] && this[hookName].length > 0) { + this[hookName].forEach(func => { + try { + func(); + } catch (e) { + console.error(`${TAG}${e.stack}`); + } + }); + } + } + + async runAsyncHookFunc(hookName) { + for (const hookItem of this[hookName]) { + try { + await hookItem(); + } catch (error) { + error['message'] += `, error in ${hookName} function`; + throw error; + } + + } + } +}; + +class SpecService { + constructor(attr) { + this.id = attr.id; + this.totalTest = 0; + this.hasError = false; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + setCurrentRunningSpec(spec) { + this.currentRunningSpec = spec; + } + + setStatus(obj) { + this.hasError = obj; + } + + getStatus() { + return this.hasError; + } + + getTestTotal() { + return this.totalTest; + } + + getCurrentRunningSpec() { + return this.currentRunningSpec; + } + + it(desc, filter, func) { + const configService = this.coreContext.getDefaultService('config'); + const currentSuiteName = this.coreContext.getDefaultService('suite').getCurrentRunningSuite().description; + if (configService.filterDesc(currentSuiteName, desc, filter, this.coreContext)) { + console.info(`${TAG}filter it :${desc}`); + } else { + let processedFunc = processFunc(this.coreContext, func); + const spec = new SpecService.Spec({description: desc, fi: filter, fn: processedFunc}); + const suiteService = this.coreContext.getDefaultService('suite'); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc); + for (let i = 1; i < specStress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + // dryRun 状态下不统计压力测试重复数据 + if (configService['dryRun'] !== 'true') { + let stress = configService.getStress(); // 命令配置压力测试 + console.info(`${TAG}stress length : ${stress}`); + for (let i = 1; i < stress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + apis() { + const _this = this; + return { + it: function (desc, filter, func) { + return _this.it(desc, filter, func); + } + }; + } +} + +SpecService.Spec = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.fi = attrs.fi; + this.fn = attrs.fn || function () { + }; + this.fail = undefined; + this.error = undefined; + this.duration = 0; + this.startTime = 0; + this.isExecuted = false; // 当前用例是否执行 + } + + setResult() { + if (this.fail) { + this.pass = false; + } else { + this.pass = true; + } + } + + run(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + coreContext.fireEvents('spec', 'specStart', this); + this.isExecuted = true; + try { + let dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + this.fn(); + } else { + let suiteParams = dataDriver.dataDriver.getSuiteParams(); + let specParams = dataDriver.dataDriver.getSpecParams(); + console.info(`${TAG}[suite params] ${JSON.stringify(suiteParams)}`); + console.info(`${TAG}[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; + specService.setStatus(true); + } + coreContext.fireEvents('spec', 'specDone', this); + } + + async asyncRun(coreContext) { + const dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + await this.fn(); + } else { + const suiteParams = dataDriver.dataDriver.getSuiteParams(); + const specParams = dataDriver.dataDriver.getSpecParams(); + console.info(`[suite params] ${JSON.stringify(suiteParams)}`); + console.info(`[spec params] ${JSON.stringify(specParams)}`); + if (this.fn.length === 0) { + await this.fn(); + } else if (specParams.length === 0) { + await this.fn(suiteParams); + } else { + for (const paramItem of specParams) { + await this.fn(Object.assign({}, paramItem, suiteParams)); + } + } + } + + this.isExecuted = true; + } + + filterCheck(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + return true; + } +}; + +class ExpectService { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + expect(actualValue) { + return this.wrapMatchers(actualValue); + } + + init(coreContext) { + this.coreContext = coreContext; + this.addMatchers(this.basicMatchers()); + } + + addMatchers(matchers) { + for (const matcherName in matchers) { + if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) { + this.matchers[matcherName] = matchers[matcherName]; + } + } + } + + basicMatchers() { + return { + assertTrue: function (actualValue) { + return { + pass: (actualValue) === true, + message: 'expect true, actualValue is ' + actualValue + }; + }, + assertEqual: function (actualValue, args) { + return { + pass: (actualValue) === args[0], + expectValue: args[0], + message: 'expect ' + actualValue + ' equals ' + args[0] + }; + }, + assertThrow: function (actual, args) { + const result = { + pass: false + }; + if (typeof actual !== 'function') { + result.message = 'toThrow\'s Actual should be a Function'; + } else { + let hasThrow = false; + let throwError; + try { + actual(); + } catch (e) { + hasThrow = true; + throwError = e; + } + if (!hasThrow) { + result.message = 'function did not throw an exception'; + } else if (throwError && throwError.message === args[0]) { + result.pass = true; + } else { + result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`; + } + } + return result; + } + }; + } + + wrapMatchers(actualValue) { + const _this = this; + const wrappedMatchers = { + // 翻转标识 + isNot: false, + + // 翻转方法 + not: function () { + this.isNot = true; + return this; + } + }; + const specService = _this.coreContext.getDefaultService('spec'); + const currentRunningSpec = specService.getCurrentRunningSpec(); + const currentRunningSuite = _this.coreContext.getDefaultService('suite').getCurrentRunningSuite(); + for (const matcherName in this.matchers) { + let result = Object.prototype.hasOwnProperty.call(this.matchers, matcherName); + if (!result) { + continue; + } + if (matcherName.search('assertPromise') == 0) { + wrappedMatchers[matcherName] = async function () { + await _this.matchers[matcherName](actualValue, arguments).then(function (result) { + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + const assertError = new AssertException(result.message); + currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError; + throw assertError; + } + }); + }; + } else { + wrappedMatchers[matcherName] = function () { + const result = _this.matchers[matcherName](actualValue, arguments); + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + const assertError = new AssertException(result.message); + currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError; + throw assertError; + } + }; + } + } + return wrappedMatchers; + } + + apis() { + const _this = this; + return { + expect: function (actualValue) { + return _this.expect(actualValue); + } + }; + } +} + +class ReportService { + constructor(attr) { + this.id = attr.id; + } + + init(coreContext) { + this.coreContext = coreContext; + this.specService = this.coreContext.getDefaultService('spec'); + this.suiteService = this.coreContext.getDefaultService('suite'); + this.duration = 0; + } + + taskStart() { + console.info(`${TAG}[start] start run suites`); + } + + async suiteStart() { + console.info(`${TAG}[suite start]${this.suiteService.getCurrentRunningSuite().description}`); + } + + async specStart() { + console.info(`${TAG}start running case '${this.specService.currentRunningSpec.description}'`); + this.index = this.index + 1; + let spec = this.specService.currentRunningSpec; + spec.startTime = await SysTestKit.getRealTime(); + } + + async specDone() { + let msg = ''; + let spec = this.specService.currentRunningSpec; + let suite = this.suiteService.currentRunningSuite; + spec.duration = await SysTestKit.getRealTime() - spec.startTime; + suite.duration += spec.duration; + if (spec.error) { + this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('errorDetail', spec.error); + } else if (spec.fail) { + this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('failDetail', spec.fail?.message); + } else { + this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms'); + } + this.formatPrint(this.specService.currentRunningSpec.error, msg); + } + + suiteDone() { + let suite = this.suiteService.currentRunningSuite; + let message = suite.hookError ? `, ${suite.hookError?.message}` : ''; + console.info(`[suite end] ${suite.description} consuming ${suite.duration} ms${message}`); + } + + taskDone() { + let msg = ''; + let summary = this.suiteService.getSummary(); + msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error; + msg += ',pass ' + summary.pass + '; consuming ' + summary.duration + 'ms'; + console.info(`${TAG}${msg}`); + console.info(`${TAG}[end] run suites end`); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + this.coreContext.getDefaultService('config').filterValid.forEach(function (item) { + console.info(`${TAG}this param ${item} is invalid`); + }); + } + } + + formatPrint(type, msg) { + switch (type) { + case 'pass': + console.info(`${TAG}[pass]${msg}`); + break; + case 'fail': + console.info(`${TAG}[fail]${msg}`); + break; + case 'failDetail': + console.info(`${TAG}[failDetail]${msg}`); + break; + case 'error': + console.info(`${TAG}[error]${msg}`); + break; + case 'errorDetail': + console.info(`${TAG}[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 +}; diff --git a/oh_modules/.ohpm/lock.json5 b/oh_modules/.ohpm/lock.json5 new file mode 100644 index 0000000..199489b --- /dev/null +++ b/oh_modules/.ohpm/lock.json5 @@ -0,0 +1,102 @@ +{ + "lockVersion": "1.0", + "settings": { + "resolveConflict": true, + "resolveConflictStrict": false, + "installAll": true + }, + "overrides": {}, + "overrideDependencyMap": {}, + "modules": { + ".": { + "name": "", + "dependencies": { + "@ohos/hypium": { + "specifier": "1.0.9", + "version": "1.0.9" + } + }, + "devDependencies": {}, + "dynamicDependencies": {}, + "maskedByOverrideDependencyMap": false + }, + "common": { + "name": "common", + "dependencies": {}, + "devDependencies": {}, + "dynamicDependencies": {}, + "maskedByOverrideDependencyMap": false + }, + "feature/recorder": { + "name": "recorder", + "dependencies": {}, + "devDependencies": { + "@ohos/common": { + "specifier": "file:common", + "version": "file:common" + } + }, + "dynamicDependencies": {}, + "maskedByOverrideDependencyMap": false + }, + "product/phone": { + "name": "phone", + "dependencies": { + "@ohos/recorder": { + "specifier": "file:feature/recorder", + "version": "file:feature/recorder" + }, + "@ohos/common": { + "specifier": "file:common", + "version": "file:common" + } + }, + "devDependencies": {}, + "dynamicDependencies": {}, + "maskedByOverrideDependencyMap": false + }, + "product/tablet": { + "name": "tablet", + "dependencies": { + "@ohos/recorder": { + "specifier": "file:feature/recorder", + "version": "file:feature/recorder" + }, + "@ohos/common": { + "specifier": "file:common", + "version": "file:common" + } + }, + "devDependencies": {}, + "dynamicDependencies": {}, + "maskedByOverrideDependencyMap": false + } + }, + "packages": { + "@ohos/hypium@1.0.9": { + "integrity": "sha512-qW5HE293s8+YRwh+6reJjR1Q08iuhay2RdPJ/JJWOI9/mjHn/zMW4i/CUfhvqlAD2w+PXUfwAYoXItc4OQpo6A==", + "storePath": "oh_modules/.ohpm/@ohos+hypium@1.0.9", + "dependencies": {}, + "dynamicDependencies": {}, + "dev": false, + "dynamic": false, + "maskedByOverrideDependencyMap": false + }, + "@ohos/common@file:common": { + "storePath": "common", + "dependencies": {}, + "dynamicDependencies": {}, + "dev": true, + "dynamic": false, + "maskedByOverrideDependencyMap": false + }, + "@ohos/recorder@file:feature/recorder": { + "storePath": "feature/recorder", + "dependencies": {}, + "dynamicDependencies": {}, + "dev": false, + "dynamic": false, + "maskedByOverrideDependencyMap": false + } + } +} \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/CHANGELOG.md b/oh_modules/.ohpm/oh_modules/@ohos/hypium/CHANGELOG.md new file mode 100644 index 0000000..79c11d2 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/CHANGELOG.md @@ -0,0 +1,50 @@ +## 1.0.9 + +- 测试hook方法支持断言与异常 +- 修复不能mock静态方法的问题 + +## 1.0.6 + +- 适配模块化编译 +- 适配IDE覆盖率数据输出 + +## 1.0.5 + +- 优化接口异常场景处理能力 +- 修复大规模压力测试下内存溢出问题 +- 修复测试脚本定义扩展原型方法与框架的兼容性问题 +- 异步promise状态判断断言与取反断言兼容 + +## 1.0.4 + +- 新增异步promise状态判断断言 +- 新增基础数据判断断言 +- 新增断言异常信息描述 +- 优化用例计时逻辑,采用相对时间计时 +- 修改用例执行过程,异步执行 +- 修复用例结果偶现的乱序问题 + +## 1.0.3 + +- 新增mock对象的能力,支持mock无参数函数 +- 新增测试套、测试用例随机执行功能 +- 解决测试套声明不规范,导致用例加载异常的问题 +- 修复命令行窗口输出乱序的问题 + +## 1.0.2 + +- 新增mock接口,判断当前mock方法状态、使用次数 +- 修复用例耗时统计问题 +- 修改断言功能,断言失败后,会抛出异常 + +## 1.0.1 +- 新增mock基础能力 +- 修复部分断言失败后,消息提示异常问题 + +## 1.0.0 +- 新增应用日志关键字查询接口,查询hilog日志中是否包含指定字符串 +- 支持用例筛选功能,用于指定测试用例的执行。可按用例名称、类型、规模、级别与测试套名称筛选 +- 支持新SDK下单元测试 +- 支持dry run 功能,通过命令行传参数,返回当前测试套用例名称全集 +- 新增框架接口声明文件,用于deveco联想 +- 修复用例状态统计问题 \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/LICENSE b/oh_modules/.ohpm/oh_modules/@ohos/hypium/LICENSE new file mode 100644 index 0000000..4947287 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/README.md b/oh_modules/.ohpm/oh_modules/@ohos/hypium/README.md new file mode 100644 index 0000000..83ddccc --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/README.md @@ -0,0 +1,219 @@ +
Hypium
+
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.9" +} +``` +注: +hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导: +[Deveco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio) + +#### 通用语法 + +- 测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。 + +| No. | API | 功能说明 | +| --- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数 | +| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 | +| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 | +| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 | +| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 | +| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数 | +| 7 | expect | 支持bool类型判断等多种断言方法 | + +#### 断言库 + +- 示例代码: + +```javascript + expect(${actualvalue}).assertX(${expectvalue}) +``` + +- 断言功能列表: + +| No. | API | 功能说明 | +| :--- | :------------------------------- | ---------------------------------------------------------------------------------------------- | +| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1) | +| 2 | assertContain | 检验actualvalue中是否包含expectvalue | +| 3 | assertDeepEquals | @since1.0.4 检验actualvalue和expectvalue(0)是否是同一个对象 | +| 4 | assertEqual | 检验actualvalue是否等于expectvalue[0] | +| 5 | assertFail | 抛出一个错误 | +| 6 | assertFalse | 检验actualvalue是否是false | +| 7 | assertTrue | 检验actualvalue是否是true | +| 8 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 | +| 9 | assertLarger | 检验actualvalue是否大于expectvalue | +| 10 | assertLess | 检验actualvalue是否小于expectvalue | +| 11 | assertNaN | @since1.0.4 检验actualvalue是否是NaN | +| 12 | assertNegUnlimited | @since1.0.4 检验actualvalue是否等于Number.NEGATIVE_INFINITY | +| 13 | assertNull | 检验actualvalue是否是null | +| 14 | assertPosUnlimited | @since1.0.4 检验actualvalue是否等于Number.POSITIVE_INFINITY | +| 15 | assertPromiseIsPending | @since1.0.4 检验actualvalue是否处于Pending状态【actualvalue为promse对象】 | +| 16 | assertPromiseIsRejected | @since1.0.4 检验actualvalue是否处于Rejected状态【同15】 | +| 17 | assertPromiseIsRejectedWith | @since1.0.4 检验actualvalue是否处于Rejected状态,并且比较执行的结果值【同15】 | +| 18 | assertPromiseIsRejectedWithError | @since1.0.4 检验actualvalue是否处于Rejected状态并有异常,同时比较异常的类型和message值【同15】 | +| 19 | assertPromiseIsResolved | @since1.0.4 检验actualvalue是否处于Resolved状态【同15】 | +| 20 | assertPromiseIsResolvedWith | @since1.0.4 检验actualvalue是否处于Resolved状态,并且比较执行的结果值【同15】 | +| 21 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue | +| 22 | assertUndefined | 检验actualvalue是否是undefined | +| 23 | not | @since1.0.4 断言结果取反 | + + + 示例代码: + +```javascript + import { describe, it, expect } from '@ohos/hypium'; + + export default async function assertCloseTest() { + describe('assertClose', function () { + it('assertClose_success', 0, function () { + let a = 100; + let b = 0.1; + expect(a).assertClose(99, b); + }) + }) + } +``` + +#### 公共系统能力 + +| No. | API | 功能描述 | +| ---- | ------------------------------------------------------- | ------------------------------------------------------------ | +| 1 | existKeyword(keyword: string, timeout: number): boolean | @since1.0.3 hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 | +| 2 | actionStart(tag: string): void | @since1.0.3 cmd窗口输出开始tag | +| 3 | actionEnd(tag: string): void | @since1.0.3 cmd窗口输出结束tag | + + 示例代码: + +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function existKeywordTest() { + describe('existKeywordTest', function () { + it('existKeyword',DEFAULT, async function () { + console.info("HelloTest"); + let isExist = await SysTestKit.existKeyword('HelloTest'); + console.info('isExist ------>' + isExist); + }) + }) +} +``` +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function actionTest() { + describe('actionTest', function () { + it('existKeyword',DEFAULT, async function () { + let tag = '[MyTest]'; + SysTestKit.actionStart(tag); + //do something + SysTestKit.actionEnd(tag); + }) + }) +} +``` + +#### 专项能力 + +- 测试用例属性筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是先在测试用例上标记用例属性后,再在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。 + +| Key | 含义说明 | Value取值范围 | +| -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| level | 用例级别 | "0","1","2","3","4", 例如:-s level 1 | +| size | 用例粒度 | "small","medium","large", 例如:-s size small | +| testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience", 例如:-s testType function | + + 示例代码 + +```javascript +import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium'; + +export default function attributeTest() { + describe('attributeTest', function () { + it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () { + console.info('Hello Test'); + }) + }) +} +``` + + 示例命令 +```shell +XX -s level 1 -s size small -s testType function +``` +该命令的作用是:筛选测试应用中同时满足a)用例级别是1 b)用例粒度是small c)用例测试类型是function 三个条件的用例执行。 + +- 测试套/测试用例名称筛选能力(测试套与用例名称用“#”号连接,多个用“,”英文逗号分隔) + +| Key | 含义说明 | Value取值范围 | +| -------- | ----------------------- | -------------------------------------------------------------------------------------------- | +| class | 指定要执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s class attributeTest#testAttributeIt | +| notClass | 指定不执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s notClass attributeTest#testAttributeIt | + + 示例命令 +```shell +XX -s class attributeTest#testAttributeIt,abilityTest#testAbilityIt +``` +该命令的作用是:筛选测试应用中attributeTest测试套下的testAttributeIt测试用例,abilityTest测试套下的testAbilityIt测试用例,只执行这两条用例。 + +- 其他能力 + +| 能力项 | Key | 含义说明 | Value取值范围 | +| ------------ | ------- | ---------------------------- | ---------------------------------------------- | +| 随机执行能力 | random | 测试套&测试用例随机执行 | true, 不传参默认为false, 例如:-s random true | +| 空跑能力 | dryRun | 显示要执行的测试用例信息全集 | true , 不传参默认为false,例如:-s dryRun true | +| 异步超时能力 | timeout | 异步用例执行的超时时间 | 正整数 , 单位ms,例如:-s timeout 5000 | + +##### 约束限制 +随机执行能力和空跑能力从npm包1.0.3版本开始支持 + +#### Mock能力 + +##### 约束限制 + +单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium/v/1.0.1)开始支持 + +## 约束 + +*** + 本模块首批接口从OpenHarmony SDK API version 8开始支持。 + +## Hypium开放能力隐私声明 + +- 我们如何收集和使用您的个人信息 + 您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。 +- SDK处理的个人信息 + 不涉及。 +- SDK集成第三方服务声明 + 不涉及。 +- SDK数据安全保护 + 不涉及。 +- SDK版本更新声明 + 为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。 + diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.d.ts b/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.d.ts new file mode 100644 index 0000000..b0b4394 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.d.ts @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const DEFAULT = 0B0000 + +export const when: when; + +export enum TestType { + FUNCTION = 0B1, + PERFORMANCE = 0B1 << 1, + POWER = 0B1 << 2, + RELIABILITY = 0B1 << 3, + SECURITY = 0B1 << 4, + GLOBAL = 0B1 << 5, + COMPATIBILITY = 0B1 << 6, + USER = 0B1 << 7, + STANDARD = 0B1 << 8, + SAFETY = 0B1 << 9, + RESILIENCE = 0B1 << 10 +} + +export enum Size { + SMALLTEST = 0B1 << 16, + MEDIUMTEST = 0B1 << 17, + LARGETEST = 0B1 << 18 +} + +export enum Level { + LEVEL0 = 0B1 << 24, + LEVEL1 = 0B1 << 25, + LEVEL2 = 0B1 << 26, + LEVEL3 = 0B1 << 27, + LEVEL4 = 0B1 << 28 +} + +export function describe(testSuiteName: string, callback: Function): void + +export function beforeEach(callback: Function): void + +export function afterEach(callback: Function): void + +export function beforeAll(callback: Function): void + +export function afterAll(callback: Function): void + +export function it(testCaseName: string, attribute: (TestType | Size | Level), callback: Function) + +export interface Assert { + assertClose(expectValue: number, precision: number): void + assertContain(expectValue: any): void + assertEqual(expectValue: any): void + assertFail(): void + assertFalse(): void + assertTrue(): void + assertInstanceOf(expectValue: string): void + assertLarger(expectValue: number): void + assertLess(expectValue: number): void + assertNull(): void + assertThrowError(expectValue: string): void + assertUndefined(): void + assertLargerOrEqual(expectValue: number):void + assertLessOrEqual(expectValue: number):void + assertNaN():void + assertNegUnlimited(): void + assertPosUnlimited(): void + not(): Assert; + assertDeepEquals(expectValue: any):void + assertPromiseIsPending(): void + assertPromiseIsRejected(): void + assertPromiseIsRejectedWith(expectValue?: any): void + assertPromiseIsRejectedWithError(...expectValue): void + assertPromiseIsResolved(): void + assertPromiseIsResolvedWith(expectValue?: any): void +} + +export function expect(actualValue?: any): Assert + +export class ArgumentMatchers { + static any; + static anyString; + static anyBoolean; + static anyNumber; + static anyObj; + static anyFunction; + static matchRegexs(Regex: RegExp): void +} + +declare interface when { + afterReturn(value: any): any + afterReturnNothing(): undefined + afterAction(action: any): any + afterThrow(e_msg: string): string + (argMatchers?: any): when; +} + +export interface VerificationMode { + times(count: Number): void + never(): void + once(): void + atLeast(count: Number): void + atMost(count: Number): void +} + +export class MockKit { + constructor() + mockFunc(obj: Object, func: Function): Function + mockObject(obj: Object): Object + verify(methodName: String, argsArray: Array): VerificationMode + ignoreMock(obj: Object, func: Function): void + clear(obj: Object): void + clearAll(): void +} + +export class SysTestKit { + static actionStart(tag: string): void + static actionEnd(tag: string): void + static existKeyword(keyword: string, timeout?: number): boolean +} + +export class Hypium { + static setData(data: {[key: string]: any}): void + static setTimeConfig(systemTime: any) + static hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void +} \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.ets b/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.ets new file mode 100644 index 0000000..355d006 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.ets @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Core from './src/main/core'; +import {ConfigService} from './src/main/module/config/configService' +import {DEFAULT, TestType, Size, Level, TAG} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +interface AbilityDelegatorArgs { + bundleName: string; + parameters: Object; + testCaseNames: string; + testRunnerClassName: string; +} + +class Hypium { + static setData(data:Object) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime:Object) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator:Object, abilityDelegatorArguments:AbilityDelegatorArgs, testsuite:Function) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + id: 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + delegator: abilityDelegator, + abilityDelegatorArguments: abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService:ConfigService = core.getDefaultService('config'); + let testParameters:Object = null; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info(`${TAG}parameters:${JSON.stringify(testParameters)}`); + configService.setConfig(testParameters); + + testsuite(); + core.execute(abilityDelegator); + } +} + +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/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.js new file mode 100644 index 0000000..affc83b --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/index.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Core from './src/main/core'; +import {DEFAULT, TestType, Size, Level, TAG} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +class Hypium { + static setData(data) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + 'delegator': abilityDelegator, + 'abilityDelegatorArguments': abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService = core.getDefaultService('config'); + + let testParameters = {}; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info(`${TAG}parameters:${JSON.stringify(testParameters)}`); + configService.setConfig(testParameters); + + testsuite(); + core.execute(abilityDelegator); + } +} + +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/oh_modules/.ohpm/oh_modules/@ohos/hypium/oh-package.json5 b/oh_modules/.ohpm/oh_modules/@ohos/hypium/oh-package.json5 new file mode 100644 index 0000000..586263c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "@ohos/hypium", + "version": "1.0.9", + "description": "A unit test framework for OpenHarmony application", + "main": "index.js", + "keywords": [], + "author": "huawei", + "license": "Apache-2.0", + "dependencies": { + } +} diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/Constant.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/Constant.js new file mode 100644 index 0000000..13f6849 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/Constant.js @@ -0,0 +1,49 @@ +/* + * 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 TAG = '[Hypium]'; + +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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/core.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/core.js new file mode 100644 index 0000000..cfcb5f1 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/core.js @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SuiteService, SpecService, ExpectService, ReportService} from './service'; +import {ConfigService} from './module/config/configService'; +import {SpecEvent, TaskEvent, SuiteEvent} from './event'; + +/** + * core service for execute testcase. + */ +class Core { + static getInstance() { + if (!this.instance) { + this.instance = new Core(); + } + return this.instance; + } + + constructor() { + this.instance = null; + this.services = { + suite: {}, + spec: {}, + config: {}, + expect: {}, + log: {}, + report: {} + + }; + this.events = { + suite: {}, + spec: {}, + task: {} + }; + } + + addService(name, service) { + let serviceObj = {}; + if (!this.services[name]) { + this.services[name] = serviceObj; + } else { + serviceObj = this.services[name]; + } + serviceObj[service.id] = service; + } + + getDefaultService(name) { + return this.services[name].default; + } + + getServices(name) { + return this.services[name]; + } + + registerEvent(serviceName, event) { + let eventObj = {}; + if (!this.events[serviceName]) { + this.events[serviceName] = eventObj; + } else { + eventObj = this.events[serviceName]; + } + eventObj[event.id] = event; + } + + unRegisterEvent(serviceName, eventID) { + const eventObj = this.events[serviceName]; + if (eventObj) { + delete eventObj[eventID]; + } + } + + subscribeEvent(serviceName, serviceObj) { + const eventObj = this.events[serviceName]; + if (eventObj) { + for (const attr in eventObj) { + eventObj[attr]['subscribeEvent'](serviceObj); + } + } + } + + async fireEvents(serviceName, eventName) { + const eventObj = this.events[serviceName]; + if (!eventObj) { + return; + } + for (const attr in eventObj) { + await eventObj[attr][eventName](); + } + } + + addToGlobal(apis) { + if (typeof globalThis !== 'undefined') { + for (let api in apis) { + globalThis[api] = apis[api]; + } + } + for (const api in apis) { + this[api] = apis[api]; + } + } + + init() { + this.addService('suite', new SuiteService({id: 'default'})); + this.addService('spec', new SpecService({id: 'default'})); + this.addService('expect', new ExpectService({id: 'default'})); + this.addService('report', new ReportService({id: 'default'})); + this.addService('config', new ConfigService({id: 'default'})); + this.registerEvent('task', new TaskEvent({id: 'default', coreContext: this})); + this.registerEvent('suite', new SuiteEvent({id: 'default', coreContext: this})); + this.registerEvent('spec', new SpecEvent({id: 'default', coreContext: this})); + this.subscribeEvent('spec', this.getDefaultService('report')); + this.subscribeEvent('suite', this.getDefaultService('report')); + this.subscribeEvent('task', this.getDefaultService('report')); + const context = this; + for (const key in this.services) { + const serviceObj = this.services[key]; + for (const serviceID in serviceObj) { + const service = serviceObj[serviceID]; + service.init(context); + + if (typeof service.apis !== 'function') { + continue; + } + const apis = service.apis(); + if (apis) { + this.addToGlobal(apis); + } + } + } + } + + execute(abilityDelegator) { + const suiteService = this.getDefaultService('suite'); + const configService = this.getDefaultService('config'); + if (configService['dryRun'] === 'true') { + (async function () { + await suiteService.dryRun(abilityDelegator); + })(); + return; + } + setTimeout(() => { + suiteService.execute(); + }, 10); + } +} + +export default Core; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/event.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/event.js new file mode 100644 index 0000000..1333a1c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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); + } + + async specStart() { + for (const monitor of this.eventMonitors) { + await monitor['specStart'](); + } + } + + async specDone() { + for (const monitor of this.eventMonitors) { + await monitor['specDone'](); + } + } +} + +class SuiteEvent { + constructor(attr) { + this.id = attr.id; + this.suiteContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async suiteStart() { + for (const monitor of this.eventMonitors) { + await monitor['suiteStart'](); + } + } + + async suiteDone() { + for (const monitor of this.eventMonitors) { + await monitor['suiteDone'](); + } + } +} + +class TaskEvent { + constructor(attr) { + this.id = attr.id; + this.coreContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async taskStart() { + for (const monitor of this.eventMonitors) { + await monitor['taskStart'](); + } + } + + async taskDone() { + for (const monitor of this.eventMonitors) { + await monitor['taskDone'](); + } + } + + incorrectFormat() { + for (const monitor of this.eventMonitors) { + monitor['incorrectFormat'](); + } + } +} + +export {SpecEvent, TaskEvent, SuiteEvent}; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/interface.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/interface.js new file mode 100644 index 0000000..40398c8 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/interface.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. + */ + +import Core from './core'; + +const core = Core.getInstance(); + +const describe = function (desc, func) { + return Reflect.has(core, 'describe') ? core.describe(desc, func) : (desc, func) => { }; +}; +const it = function (desc, filter, func) { + return Reflect.has(core, 'it') ? core.it(desc, filter, func) : (desc, filter, func) => { }; +}; +const beforeEach = function (func) { + return Reflect.has(core, 'beforeEach') ? core.beforeEach(func) : (func) => { }; +}; +const afterEach = function (func) { + return Reflect.has(core, 'afterEach') ? core.afterEach(func) : (func) => { }; +}; +const beforeAll = function (func) { + return Reflect.has(core, 'beforeAll') ? core.beforeAll(func) : (func) => { }; +}; +const afterAll = function (func) { + return Reflect.has(core, 'afterAll') ? core.afterAll(func) : (func) => { }; +}; +const expect = function (actualValue) { + return Reflect.has(core, 'expect') ? core.expect(actualValue) : (actualValue) => { }; +}; + +export { + describe, it, beforeAll, beforeEach, afterEach, afterAll, expect +}; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js new file mode 100644 index 0000000..d10d15e --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import assertNull from './assertNull'; +import assertClose from './assertClose'; +import assertContain from './assertContain'; +import assertLess from './assertLess'; +import assertLarger from './assertLarger'; +import assertFail from './assertFail'; +import assertUndefined from './assertUndefined'; +import assertFalse from './assertFalse'; +import assertInstanceOf from './assertInstanceOf'; +import assertThrowError from './assertThrowError'; +import assertLargerOrEqual from './assertLargerOrEqual' +import assertLessOrEqual from './assertLessOrEqual' +import assertNaN from './assertNaN' +import assertNegUnlimited from './assertNegUnlimited' +import assertPosUnlimited from './assertPosUnlimited' +import assertDeepEquals from './deepEquals/assertDeepEquals' +import assertPromiseIsPending from './assertPromiseIsPending'; +import assertPromiseIsRejected from './assertPromiseIsRejected'; +import assertPromiseIsRejectedWith from './assertPromiseIsRejectedWith'; +import assertPromiseIsRejectedWithError from './assertPromiseIsRejectedWithError'; +import assertPromiseIsResolved from './assertPromiseIsResolved'; +import assertPromiseIsResolvedWith from './assertPromiseIsResolvedWith'; +class ExpectExtend { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + extendsMatchers() { + this.matchers.assertNull = assertNull; + this.matchers.assertClose = assertClose; + this.matchers.assertContain = assertContain; + this.matchers.assertLess = assertLess; + this.matchers.assertLarger = assertLarger; + this.matchers.assertFail = assertFail; + this.matchers.assertUndefined = assertUndefined; + this.matchers.assertFalse = assertFalse; + this.matchers.assertInstanceOf = assertInstanceOf; + this.matchers.assertThrowError = assertThrowError; + this.matchers.assertLargerOrEqual = assertLargerOrEqual; + this.matchers.assertLessOrEqual = assertLessOrEqual; + this.matchers.assertNaN = assertNaN; + this.matchers.assertNegUnlimited = assertNegUnlimited; + this.matchers.assertPosUnlimited = assertPosUnlimited; + this.matchers.assertDeepEquals = assertDeepEquals; + this.matchers.assertPromiseIsPending = assertPromiseIsPending; + this.matchers.assertPromiseIsRejected = assertPromiseIsRejected; + this.matchers.assertPromiseIsRejectedWith = assertPromiseIsRejectedWith; + this.matchers.assertPromiseIsRejectedWithError = assertPromiseIsRejectedWithError; + this.matchers.assertPromiseIsResolved = assertPromiseIsResolved; + this.matchers.assertPromiseIsResolvedWith = assertPromiseIsResolvedWith; + } + + init(coreContext) { + this.coreContext = coreContext; + this.extendsMatchers(); + const expectService = this.coreContext.getDefaultService('expect'); + expectService.addMatchers(this.matchers); + } + + apis() { + return { + 'expect': function (actualValue) { + return this.coreContext.getDefaultService('expect').expect(actualValue); + } + }; + } +} + +export default ExpectExtend; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js new file mode 100644 index 0000000..63635be --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js new file mode 100644 index 0000000..7fba0d9 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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: 'expect false, ' + actualValue + ' do not have ' + expect[0] + }; +} + +export default assertContain; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js new file mode 100644 index 0000000..8ab4ac5 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js new file mode 100644 index 0000000..c5008e9 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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: 'expect false, actualValue is ' + actualValue + }; +} + +export default assertFalse; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js new file mode 100644 index 0000000..1e11b93 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js new file mode 100644 index 0000000..a74f4a8 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js new file mode 100644 index 0000000..e847e6c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertLargerOrEqual(actualValue, expected) { + return { + pass: (actualValue) >= expected[0], + message: (actualValue) + ' is not larger than ' + expected[0] + }; +} + +export default assertLargerOrEqual; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js new file mode 100644 index 0000000..17e84b0 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js new file mode 100644 index 0000000..f754f97 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertLessOrEqual(actualValue, expected) { + return { + pass: (actualValue) <= expected[0], + message: (actualValue) + ' is not less than ' + expected[0] + }; +} + +export default assertLessOrEqual; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js new file mode 100644 index 0000000..8d45d6a --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertNaN(actualValue) { + return { + pass: actualValue !== actualValue, + message: 'expect NaN, actualValue is ' + actualValue + }; +} + +export default assertNaN; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js new file mode 100644 index 0000000..ceac555 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function assertNegUnlimited(actualValue) { + return { + pass: actualValue === Number.NEGATIVE_INFINITY, + message: 'Expected actualValue not to be -Infinity. actualValue is,' + actualValue + }; +} + +export default assertNegUnlimited; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js new file mode 100644 index 0000000..53a7bad --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js new file mode 100644 index 0000000..6e68c0e --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function assertPosUnlimited(actualValue) { + return { + pass: actualValue === Number.POSITIVE_INFINITY, + message: 'Expected actualValue is POSITIVE_INFINITY. actualValue is,' + actualValue + }; +} + +export default assertPosUnlimited; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js new file mode 100644 index 0000000..7e2ca2c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsPending(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? {pass: true, message: 'actualValue is isPending'} + : { + pass: false, + message: 'expect isPending, actualValue is resolve' + }; + }, + function () { + return { + pass: false + , message: 'expect isPending, actualValue is reject' + }; + }); +} + +export default assertPromiseIsPending; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js new file mode 100644 index 0000000..eb8e65c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejected(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'expect isRejected, but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function () { + return {pass: true, message: 'actualValue is isRejected'}; + } + ); +} + +export default assertPromiseIsRejected; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js new file mode 100644 index 0000000..48eaf78 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWith(actualPromise, expectedValue) { + + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ('Expected a promise ' + (passed ? 'not ' : '') + + 'to be rejected with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: tips(false) + ' but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + if (JSON.stringify(actualValue) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } else { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } + } + ); +} + +export default assertPromiseIsRejectedWith; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js new file mode 100644 index 0000000..20f236f --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWithError(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'Expected a promise to be rejected but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + return matchError(actualValue, expectedValue); + } + ); + +} + +function matchError(actualValue, expectedValue) { + if (expectedValue.length == 1 && typeof expectedValue[0] === 'function') { + if (expectedValue[0].name === actualValue.__proto__.name) { + return {pass: true, message: 'actual error type is ' + actualValue.name + '.'}; + } + return {pass: false, message: `except error type is ${expectedValue[0].name},but actual is ${actualValue.name}.`}; + } + + if (expectedValue.length == 1 && typeof expectedValue[0] === 'string') { + if (expectedValue[0] === actualValue.message) { + return {pass: true, message: `actual error message is ${actualValue.message}.`}; + } + return {pass: false, message: `except error message ${expectedValue[0]},but actual is ${actualValue.message}.`}; + } + + if (expectedValue.length == 1) { + return {pass: false, message: 'When only one parameter, it should be error type or error message.'}; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name === actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; + } + return {pass: false, message: `except error message is ${expectedValue[1]},but actual is ${actualValue.message}.`}; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name !== actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: false, message: `except error type is ${expectedValue[0].name},but actual is ${actualValue.name}.`}; + } + return {pass: false, message: 'except error type and message are incorrect.'}; + } + if (expectedValue.length > 2) { + return {pass: false, message: 'Up to two parameters are supported.'}; + } +} + +export default assertPromiseIsRejectedWithError; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js new file mode 100644 index 0000000..855426c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolved(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? { + pass: false, + message: 'expect resolve, actualValue is isPending' + } + : {pass: true, message: 'actualValue is isResolved'}; + }, + function (rej) { + return { + pass: false, + message: 'Expected a promise to be resolved but it was ' + + 'rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolved; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js new file mode 100644 index 0000000..d5eb01e --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolvedWith(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ( + 'Expected a promise ' + (passed ? 'not ' : '') + + 'to be resolved with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + if (helper === got) { + return {pass: false, message: 'expect resolve, actualValue is isPending'}; + } + if (JSON.stringify(got) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was resolved with ' + JSON.stringify(got) + '.' + }; + } + return { + pass: false, + message: tips(false) + ' but it was resolved with ' + + JSON.stringify(got) + '.' + }; + }, + function (rej) { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolvedWith; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js new file mode 100644 index 0000000..749cab0 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js new file mode 100644 index 0000000..61f092d --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js new file mode 100644 index 0000000..627fb3b --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class DeepTypeUtils { + static getType_(value) { + return Object.prototype.toString.apply(value); + } + static isA_(typeName, value) { + return this.getType_(value) === '[object ' + typeName + ']'; + } + static isAsymmetricEqualityTester_(obj) { + return obj ? this.isA_('Function', obj.asymmetricMatch) : false; + } + + /** + * 是否是function + * @param value + */ + static isFunction_(value) { + return this.isA_('Function', value); + } + + /** + * 是否是undefined + * @param obj + */ + static isUndefined(obj) { + return obj === void 0; + } + + /** + * 是否是Node + * @param obj + */ + static isDomNode(obj) { + return obj !== null && + typeof obj === 'object' && + typeof obj.nodeType === 'number' && + typeof obj.nodeName === 'string'; + } + + /** + * 是否是promise对象 + * @param obj + */ + static isPromise (obj) { + return !!obj && obj.constructor === Promise; + }; + /** + * 是否是map对象 + * @param obj + */ + static isMap(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Map + ); + } + + /** + * 是否是set对象 + * @param obj 对象 + */ + static isSet(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Set + ); + } + + /** + * 对象是否有key属性 + * @param obj 对象 + * @param key 对象属性名称 + */ + static has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + } + + /** + * 获取对象的自有属性 + * @param obj 对象 + * @param isArray 是否是数组,[object Array] + */ + static keys(obj, isArray) { + const extraKeys = []; + // 获取对象所有属性 + const allKeys = this.getAllKeys(obj); + if (!isArray) { + return allKeys; + } + if (allKeys.length === 0) { + return allKeys; + } + for (const k of allKeys) { + if (typeof k === 'symbol' || !/^[0-9]+$/.test(k)) { + extraKeys.push(k); + } + } + return extraKeys; + } + + /** + * 获取obj对象的所有属性 + * @param obj obj对象 + */ + static getAllKeys(obj) { + const keys = []; + for (let key in obj) { + if(this.has(obj, key)) { + keys.push(key); + } + } + const symbols = Object.getOwnPropertySymbols(obj); + for (const sym of symbols) { + if (obj.propertyIsEnumerable(sym)) { + keys.push(sym); + } + } + return keys; + } + +} +export default DeepTypeUtils; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js new file mode 100644 index 0000000..482e28e --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DeepTypeUtils from './DeepTypeUtils' +function assertDeepEquals(actualValue, expected) { + console.log('actualValue:' + actualValue + ',expected:' + expected[0]); + let result = eq(actualValue, expected[0],[], []) + let msg = logMsg(actualValue, expected[0]); + return { + pass: result, + message: msg + }; +} + +/** + * 获取失败显示日志 + * @param actualValue 实际对象 + * @param expected 期待比较对象 + */ +function logMsg(actualValue, expected) { + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(actualValue); + const bClassName = Object.prototype.toString.call(expected); + let actualMsg; + let expectMsg; + if(aClassName == "[object Function]") { + actualMsg = "actualValue Function" + }else if(aClassName == "[object Promise]") { + actualMsg = "actualValue Promise" + }else if(aClassName == "[object Set]" || aClassName == "[object Map]") { + actualMsg = JSON.stringify(Array.from(actualValue));; + }else if(aClassName == "[object RegExp]") { + actualMsg = JSON.stringify(actualValue.source.replace("\\",""));; + }else if(aClassName == "[object BigInt]") { + actualMsg = actualValue; + } + else{ + actualMsg = JSON.stringify(actualValue); + } + if(bClassName == "[object Function]") { + expectMsg = "expected Function" + }else if(bClassName == "[object Promise]") { + expectMsg = "expected Promise" + }else if(bClassName == "[object Set]" || bClassName == "[object Map]") { + expectMsg = JSON.stringify(Array.from(expected)); + }else if(bClassName == "[object RegExp]") { + expectMsg = JSON.stringify(expected.source.replace("\\",""));; + }else if(bClassName == "[object BigInt]") { + expectMsg = expected; + } + else{ + expectMsg = JSON.stringify(expected); + } + return actualMsg + " is not deep equal " + expectMsg; +} + +function eq(a, b, aStack, bStack) { + let result = true; + console.log('a is:' + a + ',b is:' + b); + const asymmetricResult = asymmetricMatch_(a,b); + if (!DeepTypeUtils.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + + if (a instanceof Error && b instanceof Error) { + result = a.message == b.message; + return result; + } + + if (a === b) { + result = a !== 0 || 1 / a == 1 / b; + return result; + } + + if (a === null || b === null) { + result = a === b; + return result; + } + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(a); + const bClassName = Object.prototype.toString.call(b); + console.log('aClassName is:' + aClassName); + console.log('bClassName is:' + bClassName); + // 不同类型不同对象 + if (aClassName != bClassName) { + return false; + } + // 俩个string对象 + if(aClassName === '[object String]') { + result = a == String(b); + return result; + } + // 俩个Number对象 + if(aClassName === '[object Number]') { + result = a != +a ? b != +b : a === 0 && b === 0 ? 1 / a == 1 / b : a == +b; + return result; + } + + if(aClassName === '[object Date]' || aClassName === '[object Boolean]') { + result = +a == +b; + return result; + } + + // 数组 + if(aClassName === '[object ArrayBuffer]') { + return eq(new Uint8Array(a), new Uint8Array(b), aStack, bStack); + } + + // 正则表达式 + if(aClassName === '[object RegExp]') { + return ( + a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase + ); + } + + if (typeof a != 'object' || typeof b != 'object') { + return false; + } + + const aIsDomNode = DeepTypeUtils.isDomNode(a); + const bIsDomNode = DeepTypeUtils.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + result = a.isEqualNode(b); + return result; + } + if (aIsDomNode || bIsDomNode) { + return false; + } + const aIsPromise = DeepTypeUtils.isPromise(a); + const bIsPromise = DeepTypeUtils.isPromise(b); + if (aIsPromise && bIsPromise) { + return a === b; + } + let length = aStack.length; + while (length--) { + if (aStack[length] == a) { + return bStack[length] == b; + } + } + aStack.push(a); + bStack.push(b); + let size = 0; + + // 都是数组 + if(aClassName == '[object Array]') { + const aLength = a.length; + const bLength = b.length; + if (aLength !== bLength) { + // 数组长度不同,不是同一个对象 + return false; + } + for (let i = 0; i < aLength || i < bLength; i++) { + // 递归每一个元素是否相同 + result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack) && result; + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isMap(a) && DeepTypeUtils.isMap(b)) { + if (a.size != b.size) { + return false; + } + const keysA = []; + const keysB = []; + a.forEach(function(valueA, keyA) { + keysA.push(keyA); + }); + b.forEach(function(valueB, keyB) { + keysB.push(keyB); + }); + const mapKeys = [keysA, keysB]; + const cmpKeys = [keysB, keysA]; + for (let i = 0; result && i < mapKeys.length; i++) { + const mapIter = mapKeys[i]; + const cmpIter = cmpKeys[i]; + + for (let j = 0; result && j < mapIter.length; j++) { + const mapKey = mapIter[j]; + const cmpKey = cmpIter[j]; + const mapValueA = a.get(mapKey); + let mapValueB; + if ( + DeepTypeUtils.isAsymmetricEqualityTester_(mapKey) || + (DeepTypeUtils.isAsymmetricEqualityTester_(cmpKey) && + eq(mapKey, cmpKey)) + ) { + mapValueB = b.get(cmpKey); + } else { + mapValueB = b.get(mapKey); + } + result = eq(mapValueA, mapValueB, aStack, bStack); + } + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isSet(a) && DeepTypeUtils.isSet(b)) { + if (a.size != b.size) { + return false; + } + const valuesA = []; + a.forEach(function(valueA) { + valuesA.push(valueA); + }); + const valuesB = []; + b.forEach(function(valueB) { + valuesB.push(valueB); + }); + const setPairs = [[valuesA, valuesB], [valuesB, valuesA]]; + const stackPairs = [[aStack, bStack], [bStack, aStack]]; + for (let i = 0; result && i < setPairs.length; i++) { + const baseValues = setPairs[i][0]; + const otherValues = setPairs[i][1]; + const baseStack = stackPairs[i][0]; + const otherStack = stackPairs[i][1]; + for (const baseValue of baseValues) { + let found = false; + for (let j = 0; !found && j < otherValues.length; j++) { + const otherValue = otherValues[j]; + const prevStackSize = baseStack.length; + // 深度比较对象 + found = eq(baseValue, otherValue, baseStack, otherStack); + if (!found && prevStackSize !== baseStack.length) { + baseStack.splice(prevStackSize); + otherStack.splice(prevStackSize); + } + } + result = result && found; + } + } + if (!result) { + return false; + } + } else { + const aCtor = a.constructor, + bCtor = b.constructor; + if ( + aCtor !== bCtor && + DeepTypeUtils.isFunction_(aCtor) && + DeepTypeUtils.isFunction_(bCtor) && + a instanceof aCtor && + b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor) + ) { + return false; + } + } + + // 获取对象所有的属性集合 + const aKeys = DeepTypeUtils.keys(a, aClassName == '[object Array]'); + size = aKeys.length; + + // 俩个对象属性长度不一致, 俩对象不相同 + if (DeepTypeUtils.keys(b, bClassName == '[object Array]').length !== size) { + return false; + } + + // 俩对象属性数量相同, 递归比较每个属性值得值 + for (const key of aKeys) { + console.log('key is:' + key); + // b 没有 key 属性 + if(!DeepTypeUtils.has(b, key)) { + result = false; + continue; + } + if (!eq(a[key], b[key], aStack, bStack)) { + result = false; + } + } + if (!result) { + return false; + } + aStack.pop(); + bStack.pop(); + return result; +} + +function asymmetricMatch_(a, b) { + const asymmetricA = DeepTypeUtils.isAsymmetricEqualityTester_(a); + const asymmetricB = DeepTypeUtils.isAsymmetricEqualityTester_(b); + + if (asymmetricA === asymmetricB) { + return undefined; + } + +} + +/** + * 获取对象的自有属性 + * + * @param obj 对象 + * @param isArray 是否是一个数组 + */ +function keys(obj, isArray) { + const keys = []; + +} + +export default assertDeepEquals; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js new file mode 100644 index 0000000..015ab19 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js new file mode 100644 index 0000000..639dffc --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + return ObjectUtils.get(specItem, PARAMS_KEY, specParams); + } + } + } + } + return specParams; + } + + getSuiteParams() { + let suiteParams = {}; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + suiteParams = Object.assign({}, suiteParams, ObjectUtils.get(suiteItem, PARAMS_KEY, suiteParams)); + } + } + return suiteParams; + } + + getSpecStress(specDesc) { + let stress = 1; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + let tempStress = ObjectUtils.get(specItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + } + } + return stress; + } + + getSuiteStress(suiteDesc) { + let stress = 1; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + return stress; + } +} + +export default DataDriver; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/Filter.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/Filter.js new file mode 100644 index 0000000..0ca3b4f --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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.split(',').some(item => item == (this.suiteName + '#' + this.itName)); + } +} + +class SuiteAndItNameFilter { + constructor(suiteName, itName, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + } + + filterSuite() { + return !this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + } + + filterIt() { + return !this.params.split(',').map(item => item == this.itName).reduce((pre, cur) => pre || cur, false); + } +} + + +class TestTypesFilter { + constructor(suiteName, itName, fi, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + this.fi = fi; + } + + filterIt() { + return !((this.params === (this.fi & this.params)) || this.fi === 0); + } +} + +export {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter}; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/configService.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/configService.js new file mode 100644 index 0000000..94f4a76 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/config/configService.js @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter} from './Filter'; +import {TAG} from '../../Constant'; +const STRESS_RULE = /^[1-9]\d*$/; + +class ConfigService { + constructor(attr) { + this.id = attr.id; + this.supportAsync = false; + this.random = false; + this.filterValid = []; + this.filter = 0; + this.flag = false; + this.suite = null; + this.itName = null; + this.testType = null; + this.level = null; + this.size = null; + this.class = null; + this.notClass = null; + this.timeout = null; + // 遇错即停模式配置 + this.breakOnError = false; + // 压力测试配置 + this.stress = null; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + isNormalInteger(str) { + const n = Math.floor(Number(str)); + return n !== Infinity && String(n) === String(str) && n >= 0; + } + + getStress() { + if (this.stress === undefined || this.stress === '' || this.stress === null) { + return 1; + } + return !this.stress.match(STRESS_RULE) ? 1 : Number.parseInt(this.stress); + } + + basicParamValidCheck(params) { + let size = params.size; + if (size !== undefined && size !== '' && size !== null) { + let sizeArray = ['small', 'medium', 'large']; + if (sizeArray.indexOf(size) === -1) { + this.filterValid.push('size:' + size); + } + } + let level = params.level; + if (level !== undefined && level !== '' && level !== null) { + let levelArray = ['0', '1', '2', '3', '4']; + if (levelArray.indexOf(level) === -1) { + this.filterValid.push('level:' + level); + } + } + let testType = params.testType; + if (testType !== undefined && testType !== '' && testType !== null) { + let testTypeArray = ['function', 'performance', 'power', 'reliability', 'security', + 'global', 'compatibility', 'user', 'standard', 'safety', 'resilience']; + if (testTypeArray.indexOf(testType) === -1) { + this.filterValid.push('testType:' + testType); + } + } + } + + filterParamValidCheck(params) { + let timeout = params.timeout; + if (timeout !== undefined && timeout !== '' && timeout !== null) { + if (!this.isNormalInteger(timeout)) { + this.filterValid.push('timeout:' + timeout); + } + } + + let paramKeys = ['dryRun', 'random', 'breakOnError', 'coverage']; + for (const key of paramKeys) { + if (params[key] !== undefined && params[key] !== 'true' && params[key] !== 'false') { + this.filterValid.push(`${key}:${params[key]}`); + } + } + + // 压力测试参数验证,正整数 + if (params.stress !== undefined && params.stress !== '' && params.stress !== null) { + if (!params.stress.match(STRESS_RULE)) { + this.filterValid.push('stress:' + params.stress); + } + } + + let nameRule = /^[A-Za-z]{1}[\w#,.]*$/; + let paramClassKeys = ['class', 'notClass']; + for (const key of paramClassKeys) { + if (params[key] !== undefined && params[key] !== '' && params[key] !== null) { + let classArray = params[key].split(','); + classArray.forEach(item => !item.match(nameRule) ? this.filterValid.push(`${key}:${params[key]}`) : null); + } + } + } + + setConfig(params) { + this.basicParamValidCheck(params); + this.filterParamValidCheck(params); + try { + this.class = params.class; + this.notClass = params.notClass; + this.flag = params.flag || {flag: false}; + this.suite = params.suite; + this.itName = params.itName; + this.filter = params.filter; + this.testType = params.testType; + this.level = params.level; + this.size = params.size; + this.timeout = params.timeout; + this.dryRun = params.dryRun; + this.breakOnError = params.breakOnError; + this.random = params.random === 'true' ? true : false; + this.stress = params.stress; + this.coverage = params.coverage; + this.filterParam = { + testType: { + 'function': 1, + 'performance': 1 << 1, + 'power': 1 << 2, + 'reliability': 1 << 3, + 'security': 1 << 4, + 'global': 1 << 5, + 'compatibility': 1 << 6, + 'user': 1 << 7, + 'standard': 1 << 8, + 'safety': 1 << 9, + 'resilience': 1 << 10, + }, + level: { + '0': 1 << 24, + '1': 1 << 25, + '2': 1 << 26, + '3': 1 << 27, + '4': 1 << 28, + }, + size: { + 'small': 1 << 16, + 'medium': 1 << 17, + 'large': 1 << 18, + } + }; + this.parseParams(); + } catch (err) { + console.info(`${TAG}setConfig error: ${err.message}`); + } + } + + parseParams() { + if (this.filter != null) { + return; + } + let testTypeFilter = 0; + let sizeFilter = 0; + let levelFilter = 0; + if (this.testType != null) { + testTypeFilter = this.testType.split(',') + .map(item => this.filterParam.testType[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.level != null) { + levelFilter = this.level.split(',') + .map(item => this.filterParam.level[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.size != null) { + sizeFilter = this.size.split(',') + .map(item => this.filterParam.size[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + this.filter = testTypeFilter | sizeFilter | levelFilter; + console.info(`${TAG}filter params:${this.filter}`); + } + + isCurrentSuite(description) { + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + let suiteArray = this.suite.split(','); + return suiteArray.indexOf(description) !== -1; + } + return false; + } + + filterSuite(currentSuiteName) { + let filterArray = []; + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, '', this.suite)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, '', this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, '', this.notClass)); + } + + let result = filterArray.map(item => item.filterSuite()).reduce((pre, cur) => pre || cur, false); + return result; + } + + filterDesc(currentSuiteName, desc, fi, coreContext) { + let filterArray = []; + if (this.itName !== undefined && this.itName !== '' && this.itName !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, desc, this.itName)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, desc, this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, desc, this.notClass)); + } + if (typeof (this.filter) !== 'undefined' && this.filter !== 0 && fi !== 0) { + filterArray.push(new TestTypesFilter('', '', fi, this.filter)); + } + let result = filterArray.map(item => item.filterIt()).reduce((pre, cur) => pre || cur, false); + return result; + } + + isRandom() { + return this.random || false; + } + + isBreakOnError() { + return this.breakOnError !== true ? false : true; + } + + setSupportAsync(value) { + this.supportAsync = value; + } + + isSupportAsync() { + return this.supportAsync; + } + + translateParams(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = {}; + for (const key in parameters) { + if (keySet.has(key)) { + var newKey = key.replace("-s ", ""); + targetParams[newKey] = parameters[key]; + } + } + return targetParams; + } + translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key]; + } + } + return targetParams.trim(); + } + + execute() { + } +} + +export { + ConfigService +}; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js new file mode 100644 index 0000000..632a682 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "../kit/SysTestKit"; + +export async function collectCoverageData() { + if (globalThis.__coverage__ === undefined) { + return; + } + const strJson = JSON.stringify(globalThis.__coverage__); + const strLen = strJson.length; + const maxLen = 500; + const maxCount = Math.floor(strLen / maxLen); + const OHOS_REPORT_COVERAGE_DATA = 'OHOS_REPORT_COVERAGE_DATA:'; + for (let count = 0; count <= maxCount; count++) { + console.info(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); + await SysTestKit.print(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); + } +} \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js new file mode 100644 index 0000000..65d063c --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {TAG} from '../../Constant'; + +export default class SysTestKit { + + static delegator = null; + static systemTime = null; + + constructor() { + this.id = 'sysTestKit'; + this.index = 0; + } + + static actionStart(tag) { + console.info(`${TAG}${JSON.stringify(tag)}`); + var message = '\n' + 'OHOS_REPORT_ACTIONSTART: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(`${TAG}${JSON.stringify(tag)} actionStart print success`); + } + + static actionEnd(tag) { + console.info(`${TAG}${JSON.stringify(tag)}`); + var message = '\n' + 'OHOS_REPORT_ACTIONEND: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(`${TAG}${JSON.stringify(tag)} actionEnd print success`); + } + + static async existKeyword(keyword, timeout) { + let reg = new RegExp(/^[a-zA-Z0-9]{1,}$/); + if (!reg.test(keyword)) { + throw new Error('keyword must contain more than one string, and only letters and numbers are supported.'); + } + timeout = timeout || 4; + + let searchResult = false; + let cmd = 'hilog -x | grep -i \'' + keyword + '\' | wc -l'; + await executePromise(cmd, timeout).then((data) => { + searchResult = data; + }); + return searchResult; + } + static async print(message) { + if ('printSync' in SysTestKit.delegator) { + console.debug(`${TAG}printSync called ...`); + SysTestKit.delegator.printSync(message); + } else { + await SysTestKit.delegator.print(message); + } + } + + static async getRealTime() { + let currentTime = new Date().getTime(); + if (SysTestKit.systemTime !== null && SysTestKit.systemTime !== undefined) { + await SysTestKit.systemTime.getRealTime().then((time) => { + console.info(`${TAG}systemTime.getRealTime success data: ${JSON.stringify(time)}`); + currentTime = time; + }).catch((error) => { + console.error(`${TAG}failed to systemTime.getRealTime because ${JSON.stringify(error)}`); + }); + } + return currentTime; + } +} + +function executePromise(cmd, timeout) { + return new Promise((resolve, reject) => { + SysTestKit.delegator.executeShellCommand(cmd, timeout, + (error, data) => { + console.info(`${TAG}existKeyword CallBack: err : ${JSON.stringify(error)}`); + console.info(`${TAG}existKeyword CallBack: data : ${JSON.stringify(data)}`); + resolve(parseInt(data.stdResult) > 3 ? true : false); + }); + }); +} \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js new file mode 100644 index 0000000..6a9d7aa --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js new file mode 100644 index 0000000..c6a866a --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js new file mode 100644 index 0000000..1bd83be --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 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 = new Map(); + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + init() { + this.reset(); + } + + reset() { + this.mFunctions = []; + this.stubs = {}; + this.recordCalls = {}; + this.currentSetKey = new Map(); + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + clearAll() { + this.reset(); + var props = Object.keys(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + + var props = Object.getOwnPropertyNames(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + for (var key in this) { + delete this[key]; + } + } + + clear(obj) { + if (!obj) throw Error("Please enter an object to be cleaned"); + if (typeof (obj) != 'object') throw new Error('Not a object'); + this.recordMockedMethod.forEach(function (value, key, map) { + if (key) { + obj[key] = value; + } + }); + } + + ignoreMock(obj, method) { + if (typeof (obj) != 'object') throw new Error('Not a object'); + if (typeof (method) != 'function') throw new Error('Not a function'); + let og = this.recordMockedMethod.get(method.propName); + if (og) { + obj[method.propName] = og; + this.recordMockedMethod.set(method.propName, undefined); + } + } + + extend(dest, source) { + dest["stub"] = source["stub"]; + dest["afterReturn"] = source["afterReturn"]; + dest["afterReturnNothing"] = source["afterReturnNothing"]; + dest["afterAction"] = source["afterAction"]; + dest["afterThrow"] = source["afterThrow"]; + dest["stubMockedCall"] = source["stubMockedCall"]; + dest["clear"] = source["clear"]; + return dest; + } + + stubApply(f, params, returnInfo) { + let values = this.stubs.get(f); + if (!values) { + values = new Map(); + } + let key = params[0]; + if (typeof key == "undefined") { + key = "anonymous-mock-" + f.propName; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheStubKey(key)) { + key = matcher.matcheStubKey(key); + if (key) { + this.currentSetKey.set(f, key); + } + } + values.set(key, returnInfo); + this.stubs.set(f, values); + } + + getReturnInfo(f, params) { + let values = this.stubs.get(f); + if (!values) { + return undefined; + } + let retrunKet = params[0]; + if (typeof retrunKet == "undefined") { + retrunKet = "anonymous-mock-" + f.propName; + } + let stubSetKey = this.currentSetKey.get(f); + + if (stubSetKey && (typeof (retrunKet) != "undefined")) { + retrunKet = stubSetKey; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheReturnKey(params[0], undefined, stubSetKey) && matcher.matcheReturnKey(params[0], undefined, stubSetKey) != stubSetKey) { + retrunKet = params[0]; + } + + values.forEach(function (value, key, map) { + if (ArgumentMatchers.isRegExp(key) && matcher.matcheReturnKey(params[0], key)) { + retrunKet = key; + } + }); + + return values.get(retrunKet); + } + + findName(obj, value) { + let properties = this.findProperties(obj); + let name = null; + properties.filter(item => (item !== 'caller' && item !== 'arguments')).forEach( + function (va1, idx, array) { + if (obj[va1] === value) { + name = va1; + } + } + ); + return name; + } + + isFunctionFromPrototype(f, container, propName) { + if (container.constructor != Object && container.constructor.prototype !== container) { + return container.constructor.prototype[propName] === f; + } + return false; + } + + findProperties(obj, ...arg) { + function getProperty(new_obj) { + if (new_obj.__proto__ === null) { + return []; + } + let properties = Object.getOwnPropertyNames(new_obj); + return [...properties, ...getProperty(new_obj.__proto__)]; + } + return getProperty(obj); + } + + recordMethodCall(originalMethod, args) { + Function.prototype.getName = function () { + return this.name || this.toString().match(/function\s*([^(]*)\(/)[1]; + }; + let name = originalMethod.getName(); + let arglistString = name + '(' + Array.from(args).toString() + ')'; + let records = this.recordCalls.get(arglistString); + if (!records) { + records = 0; + } + records++; + this.recordCalls.set(arglistString, records); + } + + mockFunc(originalObject, originalMethod) { + let tmp = this; + this.originalMethod = originalMethod; + let f = function () { + let args = arguments; + let action = tmp.getReturnInfo(f, args); + if (originalMethod) { + tmp.recordMethodCall(originalMethod, args); + } + if (action) { + return action.apply(this, args); + } + }; + + f.container = null || originalObject; + f.original = originalMethod || null; + + if (originalObject && originalMethod) { + if (typeof (originalMethod) != 'function') throw new Error('Not a function'); + var name = this.findName(originalObject, originalMethod); + originalObject[name] = f; + this.recordMockedMethod.set(name, originalMethod); + f.propName = name; + f.originalFromPrototype = this.isFunctionFromPrototype(f.original, originalObject, f.propName); + } + f.mocker = this; + this.mFunctions.push(f); + this.extend(f, new ExtendInterface(this)); + return f; + } + + verify(methodName, argsArray) { + if (!methodName) { + throw Error("not a function name"); + } + let a = this.recordCalls.get(methodName + '(' + argsArray.toString() + ')'); + return new VerificationMode(a ? a : 0); + } + + mockObject(object) { + if (!object || typeof object === "string") { + throw Error(`this ${object} cannot be mocked`); + } + const _this = this; + let mockedObject = {}; + let keys = Reflect.ownKeys(object); + keys.filter(key => (typeof Reflect.get(object, key)) === 'function') + .forEach(key => { + mockedObject[key] = object[key]; + mockedObject[key] = _this.mockFunc(mockedObject, mockedObject[key]); + }); + return mockedObject; + } +} + +function ifMockedFunction(f) { + if (Object.prototype.toString.call(f) != "[object Function]" && + Object.prototype.toString.call(f) != "[object AsyncFunction]") { + throw Error("not a function"); + } + if (!f.stub) { + throw Error("not a mock function"); + } + return true; +} + +function when(f) { + if (ifMockedFunction(f)) { + return f.stub.bind(f); + } +} + +export {MockKit, when}; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js new file mode 100644 index 0000000..28eda2b --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {expect} from '../../interface'; + +class VerificationMode { + constructor(times) { + this.doTimes = times; + } + + times(count) { + expect(count).assertEqual(this.doTimes); + } + + never() { + console.log(this.doTimes); + expect(0).assertEqual(this.doTimes); + } + + once() { + expect(1).assertEqual(this.doTimes); + } + + atLeast(count) { + if (count > this.doTimes) { + throw Error('failed ' + count + ' greater than the actual execution times of method'); + } + } + + atMost(count) { + if (count < this.doTimes) { + throw Error('failed ' + count + ' less than the actual execution times of method'); + } + } +} + +export default VerificationMode; \ No newline at end of file diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js new file mode 100644 index 0000000..f648b11 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "../kit/SysTestKit"; +import {collectCoverageData} from '../coverage/coverageCollect'; +import {TAG} from '../../Constant'; + +class OhReport { + constructor(attr) { + this.delegator = attr.delegator; + this.abilityDelegatorArguments = attr.abilityDelegatorArguments; + this.id = 'report'; + this.index = 0; + this.duration = 0; + } + + init(coreContext) { + this.coreContext = coreContext; + this.suiteService = this.coreContext.getDefaultService('suite'); + this.specService = this.coreContext.getDefaultService('spec'); + } + + taskStart() { + } + + async taskDone() { + if (this.abilityDelegatorArguments !== null) { + this.taskDoneTime = new Date().getTime(); + let summary = this.suiteService.getSummary(); + const configService = this.coreContext.getDefaultService('config'); + if (configService['coverage'] === 'true') { + await collectCoverageData(); + } + let message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure; + message += ', Error: ' + summary.error; + message += ', Pass: ' + summary.pass; + message += ', Ignore: ' + summary.ignore; + message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n'; + let isHasError = summary.failure > 0 || summary.error > 0; + let config = this.coreContext.getDefaultService('config'); + if (config.isBreakOnError() && isHasError) { + // 未执行全部说明 + message += '\n' + 'OHOS_REPORT_RESULT: breakOnError model, Stopping whole test suite if one specific test case failed or error' + '\n'; + } + message += 'OHOS_REPORT_STATUS: taskconsuming=' + summary.duration + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + } + console.info(`${TAG}report print success`); + this.delegator.finishTest('your test finished!!!', 0, () => { }); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + var value = this.coreContext.getDefaultService('config').filterValid; + var message = 'this param ' + value.join(',') + ' is invalid' + '\n'; + this.delegator.finishTest(message, 0, () => { + }); + } + } + + async suiteStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_SUM: ' + this.suiteService.getCurrentRunningSuite().getSpecsNum(); + message += '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.suiteService.getCurrentRunningSuite().description} suiteStart print success`); + } + } + + async suiteDone() { + if (this.abilityDelegatorArguments !== null) { + const currentRunningSuite = this.suiteService.getCurrentRunningSuite(); + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: suiteconsuming=' + this.suiteService.getCurrentRunningSuite().duration; + if (currentRunningSuite.hookError) { + message += '\n' + `OHOS_REPORT_STATUS: ${currentRunningSuite.hookError.message}`; + } + message += '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.suiteService.getCurrentRunningSuite().description} suiteDone print success`); + } + } + + async specStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.specService.currentRunningSpec.description} specStart start print success`); + } + } + + async specDone() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + let errorMsg = ''; + if (this.specService.currentRunningSpec.error) { + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -1' + '\n'; + } else if (this.specService.currentRunningSpec) { + if (this.specService.currentRunningSpec.fail) { + errorMsg = this.specService.currentRunningSpec.fail?.message; + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + errorMsg; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + errorMsg + '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -2' + '\n'; + } else { + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 0' + '\n'; + } + } else { + message += '\n'; + } + message += 'OHOS_REPORT_STATUS: consuming=' + this.specService.currentRunningSpec.duration + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.specService.currentRunningSpec.description} specDone end print success`); + } + } +} + +export default OhReport; diff --git a/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js new file mode 100644 index 0000000..852fbcd --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/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/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/service.js b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/service.js new file mode 100644 index 0000000..55d04a8 --- /dev/null +++ b/oh_modules/.ohpm/oh_modules/@ohos/hypium/src/main/service.js @@ -0,0 +1,966 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "./module/kit/SysTestKit"; +import {TAG} from './Constant'; + +class AssertException extends Error { + constructor(message) { + super(); + this.name = "AssertException"; + this.message = message; + } +} + +function getFuncWithArgsZero(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + try { + await func(); + } catch (err) { + reject(err); + } + timer !== null ? clearTimeout(timer) : null; + resolve(); + }); +} + +function getFuncWithArgsOne(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout);; + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function getFuncWithArgsTwo(func, timeout, paramItem, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done, paramItem); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function processFunc(coreContext, func) { + let argNames = ((func || '').toString() + .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '') + .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2] + .split(',') // split parameters + .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim())) + .filter(String); + let funcLen = func.length; + let processedFunc; + const config = coreContext.getDefaultService('config'); + config.setSupportAsync(true); + const timeout = + (config.timeout === undefined ? 5000 : config.timeout); + const isStressTest = (coreContext.getServices('dataDriver') !== undefined || config.getStress() > 1); + switch (funcLen) { + case 0: { + processedFunc = function () { + return getFuncWithArgsZero(func, timeout, isStressTest); + }; + break; + } + case 1: { + if (argNames[0] === 'data') { + processedFunc = function (paramItem) { + func(paramItem); + }; + } else { + processedFunc = function () { + return getFuncWithArgsOne(func, timeout, isStressTest); + }; + } + break; + } + default: { + processedFunc = function (paramItem) { + return getFuncWithArgsTwo(func, timeout, paramItem, isStressTest); + }; + break; + } + } + return processedFunc; +} + +function secureRandomNumber() { + return crypto.randomBytes(8).readUInt32LE() / 0xffffffff; +} + +class SuiteService { + constructor(attr) { + this.id = attr.id; + this.rootSuite = new SuiteService.Suite({}); + this.currentRunningSuite = this.rootSuite; + this.suitesStack = [this.rootSuite]; + } + + describe(desc, func) { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterSuite(desc)) { + console.info(`${TAG}filter suite : ${desc}`); + return; + } + const suite = new SuiteService.Suite({description: desc}); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc); + for (let i = 1; i < suiteStress; i++) { + this.currentRunningSuite.childSuites.push(suite); + } + } + this.currentRunningSuite.childSuites.push(suite); + this.currentRunningSuite = suite; + this.suitesStack.push(suite); + func.call(); + let childSuite = this.suitesStack.pop(); + if (this.suitesStack.length === 0) { + this.currentRunningSuite = childSuite; + this.suitesStack.push(childSuite); + } + if (this.suitesStack.length > 1) { + this.currentRunningSuite = this.suitesStack.pop(); + } else { + this.currentRunningSuite = this.suitesStack.pop(); + this.suitesStack.push(this.currentRunningSuite); + } + } + + beforeAll(func) { + this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func)); + } + + beforeEach(func) { + this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func)); + } + + afterAll(func) { + this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func)); + } + + afterEach(func) { + this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func)); + } + + getCurrentRunningSuite() { + return this.currentRunningSuite; + } + + setCurrentRunningSuite(suite) { + this.currentRunningSuite = suite; + } + + traversalResults(suite, obj, breakOnError) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + for (const itItem of suite.specs) { + obj.total++; + if (breakOnError && (obj.error > 0 || obj.failure > 0)) { // breakOnError模式 + continue; + } + if (itItem.error) { + obj.error++; + } else if (itItem.fail) { + obj.failure++; + } else if (itItem.pass === true) { + obj.pass++; + } + } + } + + obj.duration += suite.duration; + + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + this.traversalResults(suiteItem, obj, breakOnError); + } + } + } + + async setSuiteResults(suite, error, coreContext) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + const specService = coreContext.getDefaultService('spec'); + for (const specItem of suite.specs) { + specService.setCurrentRunningSpec(specItem); + if (error instanceof AssertException) { + specItem.fail = error; + } else { + specItem.error = error; + } + await coreContext.fireEvents('spec', 'specStart', specItem); + await coreContext.fireEvents('spec', 'specDone', specItem); + } + } + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + await this.setSuiteResults(suiteItem, error, coreContext); + } + } + } + + getSummary() { + let suiteService = this.coreContext.getDefaultService('suite'); + let rootSuite = suiteService.rootSuite; + const specService = this.coreContext.getDefaultService('spec'); + const configService = this.coreContext.getDefaultService('config'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + let isBreaKOnError = breakOnError && isError; + let obj = {total: 0, failure: 0, error: 0, pass: 0, ignore: 0, duration: 0}; + for (const suiteItem of rootSuite.childSuites) { + this.traversalResults(suiteItem, obj, isBreaKOnError); + } + obj.ignore = obj.total - obj.pass - obj.failure - obj.error; + return obj; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + traversalSuites(suite, obj, configService) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return []; + } + if (suite.specs.length > 0) { + let itArray = []; + for (const itItem of suite['specs']) { + if (!configService.filterDesc(suite.description, itItem.description, itItem.fi, null)) { + itArray.push({'itName': itItem.description}); + } + } + obj[suite.description] = itArray; + } + + if (suite.childSuites.length > 0) { + let suiteArray = []; + for (const suiteItem of suite.childSuites) { + let suiteObj = {}; + this.traversalSuites(suiteItem, suiteObj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suiteArray.push(suiteObj); + } + } + obj.suites = suiteArray; + } + } + + async dryRun(abilityDelegator) { + const configService = this.coreContext.getDefaultService('config'); + let testSuitesObj = {}; + let suitesArray = []; + for (const suiteItem of this.rootSuite.childSuites) { + let obj = {}; + this.traversalSuites(suiteItem, obj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suitesArray.push(obj); + } + } + testSuitesObj['suites'] = suitesArray; + + let strJson = JSON.stringify(testSuitesObj); + let strLen = strJson.length; + let maxLen = 500; + let maxCount = Math.floor(strLen / maxLen); + + for (let count = 0; count <= maxCount; count++) { + await SysTestKit.print(strJson.substring(count * maxLen, (count + 1) * maxLen)); + } + console.info(`${TAG}dryRun print success`); + abilityDelegator.finishTest('dry run finished!!!', 0, () => { }); + } + + execute() { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterValid.length !== 0) { + this.coreContext.fireEvents('task', 'incorrectFormat'); + return; + } + + if (configService.isRandom() && this.rootSuite.childSuites.length > 0) { + this.rootSuite.childSuites.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + this.currentRunningSuite = this.rootSuite.childSuites[0]; + } + + if (configService.isSupportAsync()) { + let asyncExecute = async () => { + await this.coreContext.fireEvents('task', 'taskStart'); + await this.rootSuite.asyncRun(this.coreContext); + }; + asyncExecute().then(async () => { + await this.coreContext.fireEvents('task', 'taskDone'); + }); + } else { + this.coreContext.fireEvents('task', 'taskStart'); + this.rootSuite.run(this.coreContext); + this.coreContext.fireEvents('task', 'taskDone'); + } + } + + apis() { + const _this = this; + return { + describe: function (desc, func) { + return _this.describe(desc, func); + }, + beforeAll: function (func) { + return _this.beforeAll(func); + }, + beforeEach: function (func) { + return _this.beforeEach(func); + }, + afterAll: function (func) { + return _this.afterAll(func); + }, + afterEach: function (func) { + return _this.afterEach(func); + } + }; + } +} + +SuiteService.Suite = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.childSuites = []; + this.specs = []; + this.beforeAll = []; + this.afterAll = []; + this.beforeEach = []; + this.afterEach = []; + this.duration = 0; + this.hookError = null; + } + + pushSpec(spec) { + this.specs.push(spec); + } + + removeSpec(desc) { + this.specs = this.specs.filter((item, index) => { + return item.description !== desc; + }); + } + + getSpecsNum() { + return this.specs.length; + } + + isRun(coreContext) { + const configService = coreContext.getDefaultService('config'); + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + return breakOnError && isError; + } + + run(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteStart', this); + } + this.runHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + for (let spec in this.specs) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + this.runHookFunc('beforeEach'); + spec.run(coreContext); + this.runHookFunc('afterEach'); + } + } + if (this.childSuites.length > 0) { + for (let suite in this.childSuites) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + suite.run(coreContext); + suiteService.setCurrentRunningSuite(suite); + } + } + this.runHookFunc('afterAll'); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteDone'); + } + } + + async asyncRunSpecs(coreContext) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + const specService = coreContext.getDefaultService('spec'); + for (let specItem of this.specs) { + specService.setCurrentRunningSpec(specItem); + // 遇错即停模式,发现用例有问题,直接返回,不在执行后面的it + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log("break description :" + this.description); + break; + } + await coreContext.fireEvents('spec', 'specStart', specItem); + try { + await this.runAsyncHookFunc('beforeEach'); + await specItem.asyncRun(coreContext); + await this.runAsyncHookFunc('afterEach'); + } catch (e) { + console.error(`${TAG}${e?.stack}`); + if (e instanceof AssertException) { + specItem.fail = e; + } else { + specItem.error = e; + } + specService.setStatus(true); + } + specItem.setResult(); + await coreContext.fireEvents('spec', 'specDone', specItem); + specService.setCurrentRunningSpec(null); + } + } + + async asyncRunChildSuites(coreContext) { + for (let i = 0; i < this.childSuites.length; i++) { + // 遇错即停模式, 发现用例有问题,直接返回,不在执行后面的description + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log(`${TAG}break description : ${this.description}`); + break; + } + await this.childSuites[i].asyncRun(coreContext); + } + } + + async asyncRun(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + + suiteService.setCurrentRunningSuite(this); + suiteService.suitesStack.push(this); + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteStart', this); + } + + try { + await this.runAsyncHookFunc('beforeAll'); + } catch (error) { + console.error(`${TAG}${error?.stack}`); + this.hookError = error; + } + + if (this.hookError !== null) { + specService.setStatus(true); + await suiteService.setSuiteResults(this, this.hookError, coreContext); + } + + if (this.specs.length > 0 && this.hookError === null) { + await this.asyncRunSpecs(coreContext); + } + + if (this.childSuites.length > 0 && this.hookError === null) { + await this.asyncRunChildSuites(coreContext); + } + + try { + await this.runAsyncHookFunc('afterAll'); + } catch (error) { + console.error(`${TAG}${error?.stack}`); + this.hookError = error; + specService.setStatus(true); + } + + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteDone'); + let childSuite = suiteService.suitesStack.pop(); + if (suiteService.suitesStack.length === 0) { + suiteService.suitesStack.push(childSuite); + } + if (suiteService.suitesStack.length > 1) { + suiteService.setCurrentRunningSuite(suiteService.suitesStack.pop()); + } else { + let currentRunningSuite = suiteService.suitesStack.pop(); + suiteService.setCurrentRunningSuite(currentRunningSuite); + suiteService.suitesStack.push(currentRunningSuite); + } + } + } + + runHookFunc(hookName) { + if (this[hookName] && this[hookName].length > 0) { + this[hookName].forEach(func => { + try { + func(); + } catch (e) { + console.error(`${TAG}${e.stack}`); + } + }); + } + } + + async runAsyncHookFunc(hookName) { + for (const hookItem of this[hookName]) { + try { + await hookItem(); + } catch (error) { + error['message'] += `, error in ${hookName} function`; + throw error; + } + + } + } +}; + +class SpecService { + constructor(attr) { + this.id = attr.id; + this.totalTest = 0; + this.hasError = false; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + setCurrentRunningSpec(spec) { + this.currentRunningSpec = spec; + } + + setStatus(obj) { + this.hasError = obj; + } + + getStatus() { + return this.hasError; + } + + getTestTotal() { + return this.totalTest; + } + + getCurrentRunningSpec() { + return this.currentRunningSpec; + } + + it(desc, filter, func) { + const configService = this.coreContext.getDefaultService('config'); + const currentSuiteName = this.coreContext.getDefaultService('suite').getCurrentRunningSuite().description; + if (configService.filterDesc(currentSuiteName, desc, filter, this.coreContext)) { + console.info(`${TAG}filter it :${desc}`); + } else { + let processedFunc = processFunc(this.coreContext, func); + const spec = new SpecService.Spec({description: desc, fi: filter, fn: processedFunc}); + const suiteService = this.coreContext.getDefaultService('suite'); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc); + for (let i = 1; i < specStress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + // dryRun 状态下不统计压力测试重复数据 + if (configService['dryRun'] !== 'true') { + let stress = configService.getStress(); // 命令配置压力测试 + console.info(`${TAG}stress length : ${stress}`); + for (let i = 1; i < stress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + apis() { + const _this = this; + return { + it: function (desc, filter, func) { + return _this.it(desc, filter, func); + } + }; + } +} + +SpecService.Spec = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.fi = attrs.fi; + this.fn = attrs.fn || function () { + }; + this.fail = undefined; + this.error = undefined; + this.duration = 0; + this.startTime = 0; + this.isExecuted = false; // 当前用例是否执行 + } + + setResult() { + if (this.fail) { + this.pass = false; + } else { + this.pass = true; + } + } + + run(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + coreContext.fireEvents('spec', 'specStart', this); + this.isExecuted = true; + try { + let dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + this.fn(); + } else { + let suiteParams = dataDriver.dataDriver.getSuiteParams(); + let specParams = dataDriver.dataDriver.getSpecParams(); + console.info(`${TAG}[suite params] ${JSON.stringify(suiteParams)}`); + console.info(`${TAG}[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; + specService.setStatus(true); + } + coreContext.fireEvents('spec', 'specDone', this); + } + + async asyncRun(coreContext) { + const dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + await this.fn(); + } else { + const suiteParams = dataDriver.dataDriver.getSuiteParams(); + const specParams = dataDriver.dataDriver.getSpecParams(); + console.info(`[suite params] ${JSON.stringify(suiteParams)}`); + console.info(`[spec params] ${JSON.stringify(specParams)}`); + if (this.fn.length === 0) { + await this.fn(); + } else if (specParams.length === 0) { + await this.fn(suiteParams); + } else { + for (const paramItem of specParams) { + await this.fn(Object.assign({}, paramItem, suiteParams)); + } + } + } + + this.isExecuted = true; + } + + filterCheck(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + return true; + } +}; + +class ExpectService { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + expect(actualValue) { + return this.wrapMatchers(actualValue); + } + + init(coreContext) { + this.coreContext = coreContext; + this.addMatchers(this.basicMatchers()); + } + + addMatchers(matchers) { + for (const matcherName in matchers) { + if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) { + this.matchers[matcherName] = matchers[matcherName]; + } + } + } + + basicMatchers() { + return { + assertTrue: function (actualValue) { + return { + pass: (actualValue) === true, + message: 'expect true, actualValue is ' + actualValue + }; + }, + assertEqual: function (actualValue, args) { + return { + pass: (actualValue) === args[0], + expectValue: args[0], + message: 'expect ' + actualValue + ' equals ' + args[0] + }; + }, + assertThrow: function (actual, args) { + const result = { + pass: false + }; + if (typeof actual !== 'function') { + result.message = 'toThrow\'s Actual should be a Function'; + } else { + let hasThrow = false; + let throwError; + try { + actual(); + } catch (e) { + hasThrow = true; + throwError = e; + } + if (!hasThrow) { + result.message = 'function did not throw an exception'; + } else if (throwError && throwError.message === args[0]) { + result.pass = true; + } else { + result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`; + } + } + return result; + } + }; + } + + wrapMatchers(actualValue) { + const _this = this; + const wrappedMatchers = { + // 翻转标识 + isNot: false, + + // 翻转方法 + not: function () { + this.isNot = true; + return this; + } + }; + const specService = _this.coreContext.getDefaultService('spec'); + const currentRunningSpec = specService.getCurrentRunningSpec(); + const currentRunningSuite = _this.coreContext.getDefaultService('suite').getCurrentRunningSuite(); + for (const matcherName in this.matchers) { + let result = Object.prototype.hasOwnProperty.call(this.matchers, matcherName); + if (!result) { + continue; + } + if (matcherName.search('assertPromise') == 0) { + wrappedMatchers[matcherName] = async function () { + await _this.matchers[matcherName](actualValue, arguments).then(function (result) { + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + const assertError = new AssertException(result.message); + currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError; + throw assertError; + } + }); + }; + } else { + wrappedMatchers[matcherName] = function () { + const result = _this.matchers[matcherName](actualValue, arguments); + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + const assertError = new AssertException(result.message); + currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError; + throw assertError; + } + }; + } + } + return wrappedMatchers; + } + + apis() { + const _this = this; + return { + expect: function (actualValue) { + return _this.expect(actualValue); + } + }; + } +} + +class ReportService { + constructor(attr) { + this.id = attr.id; + } + + init(coreContext) { + this.coreContext = coreContext; + this.specService = this.coreContext.getDefaultService('spec'); + this.suiteService = this.coreContext.getDefaultService('suite'); + this.duration = 0; + } + + taskStart() { + console.info(`${TAG}[start] start run suites`); + } + + async suiteStart() { + console.info(`${TAG}[suite start]${this.suiteService.getCurrentRunningSuite().description}`); + } + + async specStart() { + console.info(`${TAG}start running case '${this.specService.currentRunningSpec.description}'`); + this.index = this.index + 1; + let spec = this.specService.currentRunningSpec; + spec.startTime = await SysTestKit.getRealTime(); + } + + async specDone() { + let msg = ''; + let spec = this.specService.currentRunningSpec; + let suite = this.suiteService.currentRunningSuite; + spec.duration = await SysTestKit.getRealTime() - spec.startTime; + suite.duration += spec.duration; + if (spec.error) { + this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('errorDetail', spec.error); + } else if (spec.fail) { + this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('failDetail', spec.fail?.message); + } else { + this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms'); + } + this.formatPrint(this.specService.currentRunningSpec.error, msg); + } + + suiteDone() { + let suite = this.suiteService.currentRunningSuite; + let message = suite.hookError ? `, ${suite.hookError?.message}` : ''; + console.info(`[suite end] ${suite.description} consuming ${suite.duration} ms${message}`); + } + + taskDone() { + let msg = ''; + let summary = this.suiteService.getSummary(); + msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error; + msg += ',pass ' + summary.pass + '; consuming ' + summary.duration + 'ms'; + console.info(`${TAG}${msg}`); + console.info(`${TAG}[end] run suites end`); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + this.coreContext.getDefaultService('config').filterValid.forEach(function (item) { + console.info(`${TAG}this param ${item} is invalid`); + }); + } + } + + formatPrint(type, msg) { + switch (type) { + case 'pass': + console.info(`${TAG}[pass]${msg}`); + break; + case 'fail': + console.info(`${TAG}[fail]${msg}`); + break; + case 'failDetail': + console.info(`${TAG}[failDetail]${msg}`); + break; + case 'error': + console.info(`${TAG}[error]${msg}`); + break; + case 'errorDetail': + console.info(`${TAG}[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 +}; diff --git a/oh_modules/@ohos/hypium/CHANGELOG.md b/oh_modules/@ohos/hypium/CHANGELOG.md new file mode 100644 index 0000000..79c11d2 --- /dev/null +++ b/oh_modules/@ohos/hypium/CHANGELOG.md @@ -0,0 +1,50 @@ +## 1.0.9 + +- 测试hook方法支持断言与异常 +- 修复不能mock静态方法的问题 + +## 1.0.6 + +- 适配模块化编译 +- 适配IDE覆盖率数据输出 + +## 1.0.5 + +- 优化接口异常场景处理能力 +- 修复大规模压力测试下内存溢出问题 +- 修复测试脚本定义扩展原型方法与框架的兼容性问题 +- 异步promise状态判断断言与取反断言兼容 + +## 1.0.4 + +- 新增异步promise状态判断断言 +- 新增基础数据判断断言 +- 新增断言异常信息描述 +- 优化用例计时逻辑,采用相对时间计时 +- 修改用例执行过程,异步执行 +- 修复用例结果偶现的乱序问题 + +## 1.0.3 + +- 新增mock对象的能力,支持mock无参数函数 +- 新增测试套、测试用例随机执行功能 +- 解决测试套声明不规范,导致用例加载异常的问题 +- 修复命令行窗口输出乱序的问题 + +## 1.0.2 + +- 新增mock接口,判断当前mock方法状态、使用次数 +- 修复用例耗时统计问题 +- 修改断言功能,断言失败后,会抛出异常 + +## 1.0.1 +- 新增mock基础能力 +- 修复部分断言失败后,消息提示异常问题 + +## 1.0.0 +- 新增应用日志关键字查询接口,查询hilog日志中是否包含指定字符串 +- 支持用例筛选功能,用于指定测试用例的执行。可按用例名称、类型、规模、级别与测试套名称筛选 +- 支持新SDK下单元测试 +- 支持dry run 功能,通过命令行传参数,返回当前测试套用例名称全集 +- 新增框架接口声明文件,用于deveco联想 +- 修复用例状态统计问题 \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/LICENSE b/oh_modules/@ohos/hypium/LICENSE new file mode 100644 index 0000000..4947287 --- /dev/null +++ b/oh_modules/@ohos/hypium/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/README.md b/oh_modules/@ohos/hypium/README.md new file mode 100644 index 0000000..83ddccc --- /dev/null +++ b/oh_modules/@ohos/hypium/README.md @@ -0,0 +1,219 @@ +
Hypium
+
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.9" +} +``` +注: +hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导: +[Deveco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio) + +#### 通用语法 + +- 测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。 + +| No. | API | 功能说明 | +| --- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数 | +| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 | +| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 | +| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 | +| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 | +| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数 | +| 7 | expect | 支持bool类型判断等多种断言方法 | + +#### 断言库 + +- 示例代码: + +```javascript + expect(${actualvalue}).assertX(${expectvalue}) +``` + +- 断言功能列表: + +| No. | API | 功能说明 | +| :--- | :------------------------------- | ---------------------------------------------------------------------------------------------- | +| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1) | +| 2 | assertContain | 检验actualvalue中是否包含expectvalue | +| 3 | assertDeepEquals | @since1.0.4 检验actualvalue和expectvalue(0)是否是同一个对象 | +| 4 | assertEqual | 检验actualvalue是否等于expectvalue[0] | +| 5 | assertFail | 抛出一个错误 | +| 6 | assertFalse | 检验actualvalue是否是false | +| 7 | assertTrue | 检验actualvalue是否是true | +| 8 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 | +| 9 | assertLarger | 检验actualvalue是否大于expectvalue | +| 10 | assertLess | 检验actualvalue是否小于expectvalue | +| 11 | assertNaN | @since1.0.4 检验actualvalue是否是NaN | +| 12 | assertNegUnlimited | @since1.0.4 检验actualvalue是否等于Number.NEGATIVE_INFINITY | +| 13 | assertNull | 检验actualvalue是否是null | +| 14 | assertPosUnlimited | @since1.0.4 检验actualvalue是否等于Number.POSITIVE_INFINITY | +| 15 | assertPromiseIsPending | @since1.0.4 检验actualvalue是否处于Pending状态【actualvalue为promse对象】 | +| 16 | assertPromiseIsRejected | @since1.0.4 检验actualvalue是否处于Rejected状态【同15】 | +| 17 | assertPromiseIsRejectedWith | @since1.0.4 检验actualvalue是否处于Rejected状态,并且比较执行的结果值【同15】 | +| 18 | assertPromiseIsRejectedWithError | @since1.0.4 检验actualvalue是否处于Rejected状态并有异常,同时比较异常的类型和message值【同15】 | +| 19 | assertPromiseIsResolved | @since1.0.4 检验actualvalue是否处于Resolved状态【同15】 | +| 20 | assertPromiseIsResolvedWith | @since1.0.4 检验actualvalue是否处于Resolved状态,并且比较执行的结果值【同15】 | +| 21 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue | +| 22 | assertUndefined | 检验actualvalue是否是undefined | +| 23 | not | @since1.0.4 断言结果取反 | + + + 示例代码: + +```javascript + import { describe, it, expect } from '@ohos/hypium'; + + export default async function assertCloseTest() { + describe('assertClose', function () { + it('assertClose_success', 0, function () { + let a = 100; + let b = 0.1; + expect(a).assertClose(99, b); + }) + }) + } +``` + +#### 公共系统能力 + +| No. | API | 功能描述 | +| ---- | ------------------------------------------------------- | ------------------------------------------------------------ | +| 1 | existKeyword(keyword: string, timeout: number): boolean | @since1.0.3 hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 | +| 2 | actionStart(tag: string): void | @since1.0.3 cmd窗口输出开始tag | +| 3 | actionEnd(tag: string): void | @since1.0.3 cmd窗口输出结束tag | + + 示例代码: + +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function existKeywordTest() { + describe('existKeywordTest', function () { + it('existKeyword',DEFAULT, async function () { + console.info("HelloTest"); + let isExist = await SysTestKit.existKeyword('HelloTest'); + console.info('isExist ------>' + isExist); + }) + }) +} +``` +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function actionTest() { + describe('actionTest', function () { + it('existKeyword',DEFAULT, async function () { + let tag = '[MyTest]'; + SysTestKit.actionStart(tag); + //do something + SysTestKit.actionEnd(tag); + }) + }) +} +``` + +#### 专项能力 + +- 测试用例属性筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是先在测试用例上标记用例属性后,再在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。 + +| Key | 含义说明 | Value取值范围 | +| -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| level | 用例级别 | "0","1","2","3","4", 例如:-s level 1 | +| size | 用例粒度 | "small","medium","large", 例如:-s size small | +| testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience", 例如:-s testType function | + + 示例代码 + +```javascript +import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium'; + +export default function attributeTest() { + describe('attributeTest', function () { + it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () { + console.info('Hello Test'); + }) + }) +} +``` + + 示例命令 +```shell +XX -s level 1 -s size small -s testType function +``` +该命令的作用是:筛选测试应用中同时满足a)用例级别是1 b)用例粒度是small c)用例测试类型是function 三个条件的用例执行。 + +- 测试套/测试用例名称筛选能力(测试套与用例名称用“#”号连接,多个用“,”英文逗号分隔) + +| Key | 含义说明 | Value取值范围 | +| -------- | ----------------------- | -------------------------------------------------------------------------------------------- | +| class | 指定要执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s class attributeTest#testAttributeIt | +| notClass | 指定不执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s notClass attributeTest#testAttributeIt | + + 示例命令 +```shell +XX -s class attributeTest#testAttributeIt,abilityTest#testAbilityIt +``` +该命令的作用是:筛选测试应用中attributeTest测试套下的testAttributeIt测试用例,abilityTest测试套下的testAbilityIt测试用例,只执行这两条用例。 + +- 其他能力 + +| 能力项 | Key | 含义说明 | Value取值范围 | +| ------------ | ------- | ---------------------------- | ---------------------------------------------- | +| 随机执行能力 | random | 测试套&测试用例随机执行 | true, 不传参默认为false, 例如:-s random true | +| 空跑能力 | dryRun | 显示要执行的测试用例信息全集 | true , 不传参默认为false,例如:-s dryRun true | +| 异步超时能力 | timeout | 异步用例执行的超时时间 | 正整数 , 单位ms,例如:-s timeout 5000 | + +##### 约束限制 +随机执行能力和空跑能力从npm包1.0.3版本开始支持 + +#### Mock能力 + +##### 约束限制 + +单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium/v/1.0.1)开始支持 + +## 约束 + +*** + 本模块首批接口从OpenHarmony SDK API version 8开始支持。 + +## Hypium开放能力隐私声明 + +- 我们如何收集和使用您的个人信息 + 您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。 +- SDK处理的个人信息 + 不涉及。 +- SDK集成第三方服务声明 + 不涉及。 +- SDK数据安全保护 + 不涉及。 +- SDK版本更新声明 + 为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。 + diff --git a/oh_modules/@ohos/hypium/index.d.ts b/oh_modules/@ohos/hypium/index.d.ts new file mode 100644 index 0000000..b0b4394 --- /dev/null +++ b/oh_modules/@ohos/hypium/index.d.ts @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const DEFAULT = 0B0000 + +export const when: when; + +export enum TestType { + FUNCTION = 0B1, + PERFORMANCE = 0B1 << 1, + POWER = 0B1 << 2, + RELIABILITY = 0B1 << 3, + SECURITY = 0B1 << 4, + GLOBAL = 0B1 << 5, + COMPATIBILITY = 0B1 << 6, + USER = 0B1 << 7, + STANDARD = 0B1 << 8, + SAFETY = 0B1 << 9, + RESILIENCE = 0B1 << 10 +} + +export enum Size { + SMALLTEST = 0B1 << 16, + MEDIUMTEST = 0B1 << 17, + LARGETEST = 0B1 << 18 +} + +export enum Level { + LEVEL0 = 0B1 << 24, + LEVEL1 = 0B1 << 25, + LEVEL2 = 0B1 << 26, + LEVEL3 = 0B1 << 27, + LEVEL4 = 0B1 << 28 +} + +export function describe(testSuiteName: string, callback: Function): void + +export function beforeEach(callback: Function): void + +export function afterEach(callback: Function): void + +export function beforeAll(callback: Function): void + +export function afterAll(callback: Function): void + +export function it(testCaseName: string, attribute: (TestType | Size | Level), callback: Function) + +export interface Assert { + assertClose(expectValue: number, precision: number): void + assertContain(expectValue: any): void + assertEqual(expectValue: any): void + assertFail(): void + assertFalse(): void + assertTrue(): void + assertInstanceOf(expectValue: string): void + assertLarger(expectValue: number): void + assertLess(expectValue: number): void + assertNull(): void + assertThrowError(expectValue: string): void + assertUndefined(): void + assertLargerOrEqual(expectValue: number):void + assertLessOrEqual(expectValue: number):void + assertNaN():void + assertNegUnlimited(): void + assertPosUnlimited(): void + not(): Assert; + assertDeepEquals(expectValue: any):void + assertPromiseIsPending(): void + assertPromiseIsRejected(): void + assertPromiseIsRejectedWith(expectValue?: any): void + assertPromiseIsRejectedWithError(...expectValue): void + assertPromiseIsResolved(): void + assertPromiseIsResolvedWith(expectValue?: any): void +} + +export function expect(actualValue?: any): Assert + +export class ArgumentMatchers { + static any; + static anyString; + static anyBoolean; + static anyNumber; + static anyObj; + static anyFunction; + static matchRegexs(Regex: RegExp): void +} + +declare interface when { + afterReturn(value: any): any + afterReturnNothing(): undefined + afterAction(action: any): any + afterThrow(e_msg: string): string + (argMatchers?: any): when; +} + +export interface VerificationMode { + times(count: Number): void + never(): void + once(): void + atLeast(count: Number): void + atMost(count: Number): void +} + +export class MockKit { + constructor() + mockFunc(obj: Object, func: Function): Function + mockObject(obj: Object): Object + verify(methodName: String, argsArray: Array): VerificationMode + ignoreMock(obj: Object, func: Function): void + clear(obj: Object): void + clearAll(): void +} + +export class SysTestKit { + static actionStart(tag: string): void + static actionEnd(tag: string): void + static existKeyword(keyword: string, timeout?: number): boolean +} + +export class Hypium { + static setData(data: {[key: string]: any}): void + static setTimeConfig(systemTime: any) + static hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void +} \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/index.ets b/oh_modules/@ohos/hypium/index.ets new file mode 100644 index 0000000..355d006 --- /dev/null +++ b/oh_modules/@ohos/hypium/index.ets @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Core from './src/main/core'; +import {ConfigService} from './src/main/module/config/configService' +import {DEFAULT, TestType, Size, Level, TAG} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +interface AbilityDelegatorArgs { + bundleName: string; + parameters: Object; + testCaseNames: string; + testRunnerClassName: string; +} + +class Hypium { + static setData(data:Object) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime:Object) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator:Object, abilityDelegatorArguments:AbilityDelegatorArgs, testsuite:Function) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + id: 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + delegator: abilityDelegator, + abilityDelegatorArguments: abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService:ConfigService = core.getDefaultService('config'); + let testParameters:Object = null; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info(`${TAG}parameters:${JSON.stringify(testParameters)}`); + configService.setConfig(testParameters); + + testsuite(); + core.execute(abilityDelegator); + } +} + +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/oh_modules/@ohos/hypium/index.js b/oh_modules/@ohos/hypium/index.js new file mode 100644 index 0000000..affc83b --- /dev/null +++ b/oh_modules/@ohos/hypium/index.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Core from './src/main/core'; +import {DEFAULT, TestType, Size, Level, TAG} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +class Hypium { + static setData(data) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + 'delegator': abilityDelegator, + 'abilityDelegatorArguments': abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService = core.getDefaultService('config'); + + let testParameters = {}; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info(`${TAG}parameters:${JSON.stringify(testParameters)}`); + configService.setConfig(testParameters); + + testsuite(); + core.execute(abilityDelegator); + } +} + +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/oh_modules/@ohos/hypium/oh-package.json5 b/oh_modules/@ohos/hypium/oh-package.json5 new file mode 100644 index 0000000..586263c --- /dev/null +++ b/oh_modules/@ohos/hypium/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "@ohos/hypium", + "version": "1.0.9", + "description": "A unit test framework for OpenHarmony application", + "main": "index.js", + "keywords": [], + "author": "huawei", + "license": "Apache-2.0", + "dependencies": { + } +} diff --git a/oh_modules/@ohos/hypium/src/main/Constant.js b/oh_modules/@ohos/hypium/src/main/Constant.js new file mode 100644 index 0000000..13f6849 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/Constant.js @@ -0,0 +1,49 @@ +/* + * 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 TAG = '[Hypium]'; + +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/oh_modules/@ohos/hypium/src/main/core.js b/oh_modules/@ohos/hypium/src/main/core.js new file mode 100644 index 0000000..cfcb5f1 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/core.js @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {SuiteService, SpecService, ExpectService, ReportService} from './service'; +import {ConfigService} from './module/config/configService'; +import {SpecEvent, TaskEvent, SuiteEvent} from './event'; + +/** + * core service for execute testcase. + */ +class Core { + static getInstance() { + if (!this.instance) { + this.instance = new Core(); + } + return this.instance; + } + + constructor() { + this.instance = null; + this.services = { + suite: {}, + spec: {}, + config: {}, + expect: {}, + log: {}, + report: {} + + }; + this.events = { + suite: {}, + spec: {}, + task: {} + }; + } + + addService(name, service) { + let serviceObj = {}; + if (!this.services[name]) { + this.services[name] = serviceObj; + } else { + serviceObj = this.services[name]; + } + serviceObj[service.id] = service; + } + + getDefaultService(name) { + return this.services[name].default; + } + + getServices(name) { + return this.services[name]; + } + + registerEvent(serviceName, event) { + let eventObj = {}; + if (!this.events[serviceName]) { + this.events[serviceName] = eventObj; + } else { + eventObj = this.events[serviceName]; + } + eventObj[event.id] = event; + } + + unRegisterEvent(serviceName, eventID) { + const eventObj = this.events[serviceName]; + if (eventObj) { + delete eventObj[eventID]; + } + } + + subscribeEvent(serviceName, serviceObj) { + const eventObj = this.events[serviceName]; + if (eventObj) { + for (const attr in eventObj) { + eventObj[attr]['subscribeEvent'](serviceObj); + } + } + } + + async fireEvents(serviceName, eventName) { + const eventObj = this.events[serviceName]; + if (!eventObj) { + return; + } + for (const attr in eventObj) { + await eventObj[attr][eventName](); + } + } + + addToGlobal(apis) { + if (typeof globalThis !== 'undefined') { + for (let api in apis) { + globalThis[api] = apis[api]; + } + } + for (const api in apis) { + this[api] = apis[api]; + } + } + + init() { + this.addService('suite', new SuiteService({id: 'default'})); + this.addService('spec', new SpecService({id: 'default'})); + this.addService('expect', new ExpectService({id: 'default'})); + this.addService('report', new ReportService({id: 'default'})); + this.addService('config', new ConfigService({id: 'default'})); + this.registerEvent('task', new TaskEvent({id: 'default', coreContext: this})); + this.registerEvent('suite', new SuiteEvent({id: 'default', coreContext: this})); + this.registerEvent('spec', new SpecEvent({id: 'default', coreContext: this})); + this.subscribeEvent('spec', this.getDefaultService('report')); + this.subscribeEvent('suite', this.getDefaultService('report')); + this.subscribeEvent('task', this.getDefaultService('report')); + const context = this; + for (const key in this.services) { + const serviceObj = this.services[key]; + for (const serviceID in serviceObj) { + const service = serviceObj[serviceID]; + service.init(context); + + if (typeof service.apis !== 'function') { + continue; + } + const apis = service.apis(); + if (apis) { + this.addToGlobal(apis); + } + } + } + } + + execute(abilityDelegator) { + const suiteService = this.getDefaultService('suite'); + const configService = this.getDefaultService('config'); + if (configService['dryRun'] === 'true') { + (async function () { + await suiteService.dryRun(abilityDelegator); + })(); + return; + } + setTimeout(() => { + suiteService.execute(); + }, 10); + } +} + +export default Core; diff --git a/oh_modules/@ohos/hypium/src/main/event.js b/oh_modules/@ohos/hypium/src/main/event.js new file mode 100644 index 0000000..1333a1c --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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); + } + + async specStart() { + for (const monitor of this.eventMonitors) { + await monitor['specStart'](); + } + } + + async specDone() { + for (const monitor of this.eventMonitors) { + await monitor['specDone'](); + } + } +} + +class SuiteEvent { + constructor(attr) { + this.id = attr.id; + this.suiteContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async suiteStart() { + for (const monitor of this.eventMonitors) { + await monitor['suiteStart'](); + } + } + + async suiteDone() { + for (const monitor of this.eventMonitors) { + await monitor['suiteDone'](); + } + } +} + +class TaskEvent { + constructor(attr) { + this.id = attr.id; + this.coreContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async taskStart() { + for (const monitor of this.eventMonitors) { + await monitor['taskStart'](); + } + } + + async taskDone() { + for (const monitor of this.eventMonitors) { + await monitor['taskDone'](); + } + } + + incorrectFormat() { + for (const monitor of this.eventMonitors) { + monitor['incorrectFormat'](); + } + } +} + +export {SpecEvent, TaskEvent, SuiteEvent}; diff --git a/oh_modules/@ohos/hypium/src/main/interface.js b/oh_modules/@ohos/hypium/src/main/interface.js new file mode 100644 index 0000000..40398c8 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/interface.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. + */ + +import Core from './core'; + +const core = Core.getInstance(); + +const describe = function (desc, func) { + return Reflect.has(core, 'describe') ? core.describe(desc, func) : (desc, func) => { }; +}; +const it = function (desc, filter, func) { + return Reflect.has(core, 'it') ? core.it(desc, filter, func) : (desc, filter, func) => { }; +}; +const beforeEach = function (func) { + return Reflect.has(core, 'beforeEach') ? core.beforeEach(func) : (func) => { }; +}; +const afterEach = function (func) { + return Reflect.has(core, 'afterEach') ? core.afterEach(func) : (func) => { }; +}; +const beforeAll = function (func) { + return Reflect.has(core, 'beforeAll') ? core.beforeAll(func) : (func) => { }; +}; +const afterAll = function (func) { + return Reflect.has(core, 'afterAll') ? core.afterAll(func) : (func) => { }; +}; +const expect = function (actualValue) { + return Reflect.has(core, 'expect') ? core.expect(actualValue) : (actualValue) => { }; +}; + +export { + describe, it, beforeAll, beforeEach, afterEach, afterAll, expect +}; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js b/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js new file mode 100644 index 0000000..d10d15e --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import assertNull from './assertNull'; +import assertClose from './assertClose'; +import assertContain from './assertContain'; +import assertLess from './assertLess'; +import assertLarger from './assertLarger'; +import assertFail from './assertFail'; +import assertUndefined from './assertUndefined'; +import assertFalse from './assertFalse'; +import assertInstanceOf from './assertInstanceOf'; +import assertThrowError from './assertThrowError'; +import assertLargerOrEqual from './assertLargerOrEqual' +import assertLessOrEqual from './assertLessOrEqual' +import assertNaN from './assertNaN' +import assertNegUnlimited from './assertNegUnlimited' +import assertPosUnlimited from './assertPosUnlimited' +import assertDeepEquals from './deepEquals/assertDeepEquals' +import assertPromiseIsPending from './assertPromiseIsPending'; +import assertPromiseIsRejected from './assertPromiseIsRejected'; +import assertPromiseIsRejectedWith from './assertPromiseIsRejectedWith'; +import assertPromiseIsRejectedWithError from './assertPromiseIsRejectedWithError'; +import assertPromiseIsResolved from './assertPromiseIsResolved'; +import assertPromiseIsResolvedWith from './assertPromiseIsResolvedWith'; +class ExpectExtend { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + extendsMatchers() { + this.matchers.assertNull = assertNull; + this.matchers.assertClose = assertClose; + this.matchers.assertContain = assertContain; + this.matchers.assertLess = assertLess; + this.matchers.assertLarger = assertLarger; + this.matchers.assertFail = assertFail; + this.matchers.assertUndefined = assertUndefined; + this.matchers.assertFalse = assertFalse; + this.matchers.assertInstanceOf = assertInstanceOf; + this.matchers.assertThrowError = assertThrowError; + this.matchers.assertLargerOrEqual = assertLargerOrEqual; + this.matchers.assertLessOrEqual = assertLessOrEqual; + this.matchers.assertNaN = assertNaN; + this.matchers.assertNegUnlimited = assertNegUnlimited; + this.matchers.assertPosUnlimited = assertPosUnlimited; + this.matchers.assertDeepEquals = assertDeepEquals; + this.matchers.assertPromiseIsPending = assertPromiseIsPending; + this.matchers.assertPromiseIsRejected = assertPromiseIsRejected; + this.matchers.assertPromiseIsRejectedWith = assertPromiseIsRejectedWith; + this.matchers.assertPromiseIsRejectedWithError = assertPromiseIsRejectedWithError; + this.matchers.assertPromiseIsResolved = assertPromiseIsResolved; + this.matchers.assertPromiseIsResolvedWith = assertPromiseIsResolvedWith; + } + + init(coreContext) { + this.coreContext = coreContext; + this.extendsMatchers(); + const expectService = this.coreContext.getDefaultService('expect'); + expectService.addMatchers(this.matchers); + } + + apis() { + return { + 'expect': function (actualValue) { + return this.coreContext.getDefaultService('expect').expect(actualValue); + } + }; + } +} + +export default ExpectExtend; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js new file mode 100644 index 0000000..63635be --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js new file mode 100644 index 0000000..7fba0d9 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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: 'expect false, ' + actualValue + ' do not have ' + expect[0] + }; +} + +export default assertContain; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js new file mode 100644 index 0000000..8ab4ac5 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js new file mode 100644 index 0000000..c5008e9 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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: 'expect false, actualValue is ' + actualValue + }; +} + +export default assertFalse; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js new file mode 100644 index 0000000..1e11b93 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js new file mode 100644 index 0000000..a74f4a8 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js new file mode 100644 index 0000000..e847e6c --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertLargerOrEqual(actualValue, expected) { + return { + pass: (actualValue) >= expected[0], + message: (actualValue) + ' is not larger than ' + expected[0] + }; +} + +export default assertLargerOrEqual; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js new file mode 100644 index 0000000..17e84b0 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js new file mode 100644 index 0000000..f754f97 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertLessOrEqual(actualValue, expected) { + return { + pass: (actualValue) <= expected[0], + message: (actualValue) + ' is not less than ' + expected[0] + }; +} + +export default assertLessOrEqual; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js new file mode 100644 index 0000000..8d45d6a --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assertNaN(actualValue) { + return { + pass: actualValue !== actualValue, + message: 'expect NaN, actualValue is ' + actualValue + }; +} + +export default assertNaN; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js new file mode 100644 index 0000000..ceac555 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function assertNegUnlimited(actualValue) { + return { + pass: actualValue === Number.NEGATIVE_INFINITY, + message: 'Expected actualValue not to be -Infinity. actualValue is,' + actualValue + }; +} + +export default assertNegUnlimited; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js new file mode 100644 index 0000000..53a7bad --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js new file mode 100644 index 0000000..6e68c0e --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function assertPosUnlimited(actualValue) { + return { + pass: actualValue === Number.POSITIVE_INFINITY, + message: 'Expected actualValue is POSITIVE_INFINITY. actualValue is,' + actualValue + }; +} + +export default assertPosUnlimited; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js new file mode 100644 index 0000000..7e2ca2c --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsPending(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? {pass: true, message: 'actualValue is isPending'} + : { + pass: false, + message: 'expect isPending, actualValue is resolve' + }; + }, + function () { + return { + pass: false + , message: 'expect isPending, actualValue is reject' + }; + }); +} + +export default assertPromiseIsPending; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js new file mode 100644 index 0000000..eb8e65c --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejected(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'expect isRejected, but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function () { + return {pass: true, message: 'actualValue is isRejected'}; + } + ); +} + +export default assertPromiseIsRejected; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js new file mode 100644 index 0000000..48eaf78 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWith(actualPromise, expectedValue) { + + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ('Expected a promise ' + (passed ? 'not ' : '') + + 'to be rejected with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: tips(false) + ' but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + if (JSON.stringify(actualValue) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } else { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } + } + ); +} + +export default assertPromiseIsRejectedWith; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js new file mode 100644 index 0000000..20f236f --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWithError(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'Expected a promise to be rejected but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + return matchError(actualValue, expectedValue); + } + ); + +} + +function matchError(actualValue, expectedValue) { + if (expectedValue.length == 1 && typeof expectedValue[0] === 'function') { + if (expectedValue[0].name === actualValue.__proto__.name) { + return {pass: true, message: 'actual error type is ' + actualValue.name + '.'}; + } + return {pass: false, message: `except error type is ${expectedValue[0].name},but actual is ${actualValue.name}.`}; + } + + if (expectedValue.length == 1 && typeof expectedValue[0] === 'string') { + if (expectedValue[0] === actualValue.message) { + return {pass: true, message: `actual error message is ${actualValue.message}.`}; + } + return {pass: false, message: `except error message ${expectedValue[0]},but actual is ${actualValue.message}.`}; + } + + if (expectedValue.length == 1) { + return {pass: false, message: 'When only one parameter, it should be error type or error message.'}; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name === actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; + } + return {pass: false, message: `except error message is ${expectedValue[1]},but actual is ${actualValue.message}.`}; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name !== actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: false, message: `except error type is ${expectedValue[0].name},but actual is ${actualValue.name}.`}; + } + return {pass: false, message: 'except error type and message are incorrect.'}; + } + if (expectedValue.length > 2) { + return {pass: false, message: 'Up to two parameters are supported.'}; + } +} + +export default assertPromiseIsRejectedWithError; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js new file mode 100644 index 0000000..855426c --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolved(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? { + pass: false, + message: 'expect resolve, actualValue is isPending' + } + : {pass: true, message: 'actualValue is isResolved'}; + }, + function (rej) { + return { + pass: false, + message: 'Expected a promise to be resolved but it was ' + + 'rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolved; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js new file mode 100644 index 0000000..d5eb01e --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolvedWith(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ( + 'Expected a promise ' + (passed ? 'not ' : '') + + 'to be resolved with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + if (helper === got) { + return {pass: false, message: 'expect resolve, actualValue is isPending'}; + } + if (JSON.stringify(got) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was resolved with ' + JSON.stringify(got) + '.' + }; + } + return { + pass: false, + message: tips(false) + ' but it was resolved with ' + + JSON.stringify(got) + '.' + }; + }, + function (rej) { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolvedWith; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js new file mode 100644 index 0000000..749cab0 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js b/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js new file mode 100644 index 0000000..61f092d --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js b/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js new file mode 100644 index 0000000..627fb3b --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class DeepTypeUtils { + static getType_(value) { + return Object.prototype.toString.apply(value); + } + static isA_(typeName, value) { + return this.getType_(value) === '[object ' + typeName + ']'; + } + static isAsymmetricEqualityTester_(obj) { + return obj ? this.isA_('Function', obj.asymmetricMatch) : false; + } + + /** + * 是否是function + * @param value + */ + static isFunction_(value) { + return this.isA_('Function', value); + } + + /** + * 是否是undefined + * @param obj + */ + static isUndefined(obj) { + return obj === void 0; + } + + /** + * 是否是Node + * @param obj + */ + static isDomNode(obj) { + return obj !== null && + typeof obj === 'object' && + typeof obj.nodeType === 'number' && + typeof obj.nodeName === 'string'; + } + + /** + * 是否是promise对象 + * @param obj + */ + static isPromise (obj) { + return !!obj && obj.constructor === Promise; + }; + /** + * 是否是map对象 + * @param obj + */ + static isMap(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Map + ); + } + + /** + * 是否是set对象 + * @param obj 对象 + */ + static isSet(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Set + ); + } + + /** + * 对象是否有key属性 + * @param obj 对象 + * @param key 对象属性名称 + */ + static has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + } + + /** + * 获取对象的自有属性 + * @param obj 对象 + * @param isArray 是否是数组,[object Array] + */ + static keys(obj, isArray) { + const extraKeys = []; + // 获取对象所有属性 + const allKeys = this.getAllKeys(obj); + if (!isArray) { + return allKeys; + } + if (allKeys.length === 0) { + return allKeys; + } + for (const k of allKeys) { + if (typeof k === 'symbol' || !/^[0-9]+$/.test(k)) { + extraKeys.push(k); + } + } + return extraKeys; + } + + /** + * 获取obj对象的所有属性 + * @param obj obj对象 + */ + static getAllKeys(obj) { + const keys = []; + for (let key in obj) { + if(this.has(obj, key)) { + keys.push(key); + } + } + const symbols = Object.getOwnPropertySymbols(obj); + for (const sym of symbols) { + if (obj.propertyIsEnumerable(sym)) { + keys.push(sym); + } + } + return keys; + } + +} +export default DeepTypeUtils; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js b/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js new file mode 100644 index 0000000..482e28e --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DeepTypeUtils from './DeepTypeUtils' +function assertDeepEquals(actualValue, expected) { + console.log('actualValue:' + actualValue + ',expected:' + expected[0]); + let result = eq(actualValue, expected[0],[], []) + let msg = logMsg(actualValue, expected[0]); + return { + pass: result, + message: msg + }; +} + +/** + * 获取失败显示日志 + * @param actualValue 实际对象 + * @param expected 期待比较对象 + */ +function logMsg(actualValue, expected) { + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(actualValue); + const bClassName = Object.prototype.toString.call(expected); + let actualMsg; + let expectMsg; + if(aClassName == "[object Function]") { + actualMsg = "actualValue Function" + }else if(aClassName == "[object Promise]") { + actualMsg = "actualValue Promise" + }else if(aClassName == "[object Set]" || aClassName == "[object Map]") { + actualMsg = JSON.stringify(Array.from(actualValue));; + }else if(aClassName == "[object RegExp]") { + actualMsg = JSON.stringify(actualValue.source.replace("\\",""));; + }else if(aClassName == "[object BigInt]") { + actualMsg = actualValue; + } + else{ + actualMsg = JSON.stringify(actualValue); + } + if(bClassName == "[object Function]") { + expectMsg = "expected Function" + }else if(bClassName == "[object Promise]") { + expectMsg = "expected Promise" + }else if(bClassName == "[object Set]" || bClassName == "[object Map]") { + expectMsg = JSON.stringify(Array.from(expected)); + }else if(bClassName == "[object RegExp]") { + expectMsg = JSON.stringify(expected.source.replace("\\",""));; + }else if(bClassName == "[object BigInt]") { + expectMsg = expected; + } + else{ + expectMsg = JSON.stringify(expected); + } + return actualMsg + " is not deep equal " + expectMsg; +} + +function eq(a, b, aStack, bStack) { + let result = true; + console.log('a is:' + a + ',b is:' + b); + const asymmetricResult = asymmetricMatch_(a,b); + if (!DeepTypeUtils.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + + if (a instanceof Error && b instanceof Error) { + result = a.message == b.message; + return result; + } + + if (a === b) { + result = a !== 0 || 1 / a == 1 / b; + return result; + } + + if (a === null || b === null) { + result = a === b; + return result; + } + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(a); + const bClassName = Object.prototype.toString.call(b); + console.log('aClassName is:' + aClassName); + console.log('bClassName is:' + bClassName); + // 不同类型不同对象 + if (aClassName != bClassName) { + return false; + } + // 俩个string对象 + if(aClassName === '[object String]') { + result = a == String(b); + return result; + } + // 俩个Number对象 + if(aClassName === '[object Number]') { + result = a != +a ? b != +b : a === 0 && b === 0 ? 1 / a == 1 / b : a == +b; + return result; + } + + if(aClassName === '[object Date]' || aClassName === '[object Boolean]') { + result = +a == +b; + return result; + } + + // 数组 + if(aClassName === '[object ArrayBuffer]') { + return eq(new Uint8Array(a), new Uint8Array(b), aStack, bStack); + } + + // 正则表达式 + if(aClassName === '[object RegExp]') { + return ( + a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase + ); + } + + if (typeof a != 'object' || typeof b != 'object') { + return false; + } + + const aIsDomNode = DeepTypeUtils.isDomNode(a); + const bIsDomNode = DeepTypeUtils.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + result = a.isEqualNode(b); + return result; + } + if (aIsDomNode || bIsDomNode) { + return false; + } + const aIsPromise = DeepTypeUtils.isPromise(a); + const bIsPromise = DeepTypeUtils.isPromise(b); + if (aIsPromise && bIsPromise) { + return a === b; + } + let length = aStack.length; + while (length--) { + if (aStack[length] == a) { + return bStack[length] == b; + } + } + aStack.push(a); + bStack.push(b); + let size = 0; + + // 都是数组 + if(aClassName == '[object Array]') { + const aLength = a.length; + const bLength = b.length; + if (aLength !== bLength) { + // 数组长度不同,不是同一个对象 + return false; + } + for (let i = 0; i < aLength || i < bLength; i++) { + // 递归每一个元素是否相同 + result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack) && result; + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isMap(a) && DeepTypeUtils.isMap(b)) { + if (a.size != b.size) { + return false; + } + const keysA = []; + const keysB = []; + a.forEach(function(valueA, keyA) { + keysA.push(keyA); + }); + b.forEach(function(valueB, keyB) { + keysB.push(keyB); + }); + const mapKeys = [keysA, keysB]; + const cmpKeys = [keysB, keysA]; + for (let i = 0; result && i < mapKeys.length; i++) { + const mapIter = mapKeys[i]; + const cmpIter = cmpKeys[i]; + + for (let j = 0; result && j < mapIter.length; j++) { + const mapKey = mapIter[j]; + const cmpKey = cmpIter[j]; + const mapValueA = a.get(mapKey); + let mapValueB; + if ( + DeepTypeUtils.isAsymmetricEqualityTester_(mapKey) || + (DeepTypeUtils.isAsymmetricEqualityTester_(cmpKey) && + eq(mapKey, cmpKey)) + ) { + mapValueB = b.get(cmpKey); + } else { + mapValueB = b.get(mapKey); + } + result = eq(mapValueA, mapValueB, aStack, bStack); + } + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isSet(a) && DeepTypeUtils.isSet(b)) { + if (a.size != b.size) { + return false; + } + const valuesA = []; + a.forEach(function(valueA) { + valuesA.push(valueA); + }); + const valuesB = []; + b.forEach(function(valueB) { + valuesB.push(valueB); + }); + const setPairs = [[valuesA, valuesB], [valuesB, valuesA]]; + const stackPairs = [[aStack, bStack], [bStack, aStack]]; + for (let i = 0; result && i < setPairs.length; i++) { + const baseValues = setPairs[i][0]; + const otherValues = setPairs[i][1]; + const baseStack = stackPairs[i][0]; + const otherStack = stackPairs[i][1]; + for (const baseValue of baseValues) { + let found = false; + for (let j = 0; !found && j < otherValues.length; j++) { + const otherValue = otherValues[j]; + const prevStackSize = baseStack.length; + // 深度比较对象 + found = eq(baseValue, otherValue, baseStack, otherStack); + if (!found && prevStackSize !== baseStack.length) { + baseStack.splice(prevStackSize); + otherStack.splice(prevStackSize); + } + } + result = result && found; + } + } + if (!result) { + return false; + } + } else { + const aCtor = a.constructor, + bCtor = b.constructor; + if ( + aCtor !== bCtor && + DeepTypeUtils.isFunction_(aCtor) && + DeepTypeUtils.isFunction_(bCtor) && + a instanceof aCtor && + b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor) + ) { + return false; + } + } + + // 获取对象所有的属性集合 + const aKeys = DeepTypeUtils.keys(a, aClassName == '[object Array]'); + size = aKeys.length; + + // 俩个对象属性长度不一致, 俩对象不相同 + if (DeepTypeUtils.keys(b, bClassName == '[object Array]').length !== size) { + return false; + } + + // 俩对象属性数量相同, 递归比较每个属性值得值 + for (const key of aKeys) { + console.log('key is:' + key); + // b 没有 key 属性 + if(!DeepTypeUtils.has(b, key)) { + result = false; + continue; + } + if (!eq(a[key], b[key], aStack, bStack)) { + result = false; + } + } + if (!result) { + return false; + } + aStack.pop(); + bStack.pop(); + return result; +} + +function asymmetricMatch_(a, b) { + const asymmetricA = DeepTypeUtils.isAsymmetricEqualityTester_(a); + const asymmetricB = DeepTypeUtils.isAsymmetricEqualityTester_(b); + + if (asymmetricA === asymmetricB) { + return undefined; + } + +} + +/** + * 获取对象的自有属性 + * + * @param obj 对象 + * @param isArray 是否是一个数组 + */ +function keys(obj, isArray) { + const keys = []; + +} + +export default assertDeepEquals; diff --git a/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js b/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js new file mode 100644 index 0000000..015ab19 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js b/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js new file mode 100644 index 0000000..639dffc --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + return ObjectUtils.get(specItem, PARAMS_KEY, specParams); + } + } + } + } + return specParams; + } + + getSuiteParams() { + let suiteParams = {}; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + suiteParams = Object.assign({}, suiteParams, ObjectUtils.get(suiteItem, PARAMS_KEY, suiteParams)); + } + } + return suiteParams; + } + + getSpecStress(specDesc) { + let stress = 1; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + let tempStress = ObjectUtils.get(specItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + } + } + return stress; + } + + getSuiteStress(suiteDesc) { + let stress = 1; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + return stress; + } +} + +export default DataDriver; diff --git a/oh_modules/@ohos/hypium/src/main/module/config/Filter.js b/oh_modules/@ohos/hypium/src/main/module/config/Filter.js new file mode 100644 index 0000000..0ca3b4f --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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.split(',').some(item => item == (this.suiteName + '#' + this.itName)); + } +} + +class SuiteAndItNameFilter { + constructor(suiteName, itName, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + } + + filterSuite() { + return !this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + } + + filterIt() { + return !this.params.split(',').map(item => item == this.itName).reduce((pre, cur) => pre || cur, false); + } +} + + +class TestTypesFilter { + constructor(suiteName, itName, fi, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + this.fi = fi; + } + + filterIt() { + return !((this.params === (this.fi & this.params)) || this.fi === 0); + } +} + +export {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter}; diff --git a/oh_modules/@ohos/hypium/src/main/module/config/configService.js b/oh_modules/@ohos/hypium/src/main/module/config/configService.js new file mode 100644 index 0000000..94f4a76 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/config/configService.js @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter} from './Filter'; +import {TAG} from '../../Constant'; +const STRESS_RULE = /^[1-9]\d*$/; + +class ConfigService { + constructor(attr) { + this.id = attr.id; + this.supportAsync = false; + this.random = false; + this.filterValid = []; + this.filter = 0; + this.flag = false; + this.suite = null; + this.itName = null; + this.testType = null; + this.level = null; + this.size = null; + this.class = null; + this.notClass = null; + this.timeout = null; + // 遇错即停模式配置 + this.breakOnError = false; + // 压力测试配置 + this.stress = null; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + isNormalInteger(str) { + const n = Math.floor(Number(str)); + return n !== Infinity && String(n) === String(str) && n >= 0; + } + + getStress() { + if (this.stress === undefined || this.stress === '' || this.stress === null) { + return 1; + } + return !this.stress.match(STRESS_RULE) ? 1 : Number.parseInt(this.stress); + } + + basicParamValidCheck(params) { + let size = params.size; + if (size !== undefined && size !== '' && size !== null) { + let sizeArray = ['small', 'medium', 'large']; + if (sizeArray.indexOf(size) === -1) { + this.filterValid.push('size:' + size); + } + } + let level = params.level; + if (level !== undefined && level !== '' && level !== null) { + let levelArray = ['0', '1', '2', '3', '4']; + if (levelArray.indexOf(level) === -1) { + this.filterValid.push('level:' + level); + } + } + let testType = params.testType; + if (testType !== undefined && testType !== '' && testType !== null) { + let testTypeArray = ['function', 'performance', 'power', 'reliability', 'security', + 'global', 'compatibility', 'user', 'standard', 'safety', 'resilience']; + if (testTypeArray.indexOf(testType) === -1) { + this.filterValid.push('testType:' + testType); + } + } + } + + filterParamValidCheck(params) { + let timeout = params.timeout; + if (timeout !== undefined && timeout !== '' && timeout !== null) { + if (!this.isNormalInteger(timeout)) { + this.filterValid.push('timeout:' + timeout); + } + } + + let paramKeys = ['dryRun', 'random', 'breakOnError', 'coverage']; + for (const key of paramKeys) { + if (params[key] !== undefined && params[key] !== 'true' && params[key] !== 'false') { + this.filterValid.push(`${key}:${params[key]}`); + } + } + + // 压力测试参数验证,正整数 + if (params.stress !== undefined && params.stress !== '' && params.stress !== null) { + if (!params.stress.match(STRESS_RULE)) { + this.filterValid.push('stress:' + params.stress); + } + } + + let nameRule = /^[A-Za-z]{1}[\w#,.]*$/; + let paramClassKeys = ['class', 'notClass']; + for (const key of paramClassKeys) { + if (params[key] !== undefined && params[key] !== '' && params[key] !== null) { + let classArray = params[key].split(','); + classArray.forEach(item => !item.match(nameRule) ? this.filterValid.push(`${key}:${params[key]}`) : null); + } + } + } + + setConfig(params) { + this.basicParamValidCheck(params); + this.filterParamValidCheck(params); + try { + this.class = params.class; + this.notClass = params.notClass; + this.flag = params.flag || {flag: false}; + this.suite = params.suite; + this.itName = params.itName; + this.filter = params.filter; + this.testType = params.testType; + this.level = params.level; + this.size = params.size; + this.timeout = params.timeout; + this.dryRun = params.dryRun; + this.breakOnError = params.breakOnError; + this.random = params.random === 'true' ? true : false; + this.stress = params.stress; + this.coverage = params.coverage; + this.filterParam = { + testType: { + 'function': 1, + 'performance': 1 << 1, + 'power': 1 << 2, + 'reliability': 1 << 3, + 'security': 1 << 4, + 'global': 1 << 5, + 'compatibility': 1 << 6, + 'user': 1 << 7, + 'standard': 1 << 8, + 'safety': 1 << 9, + 'resilience': 1 << 10, + }, + level: { + '0': 1 << 24, + '1': 1 << 25, + '2': 1 << 26, + '3': 1 << 27, + '4': 1 << 28, + }, + size: { + 'small': 1 << 16, + 'medium': 1 << 17, + 'large': 1 << 18, + } + }; + this.parseParams(); + } catch (err) { + console.info(`${TAG}setConfig error: ${err.message}`); + } + } + + parseParams() { + if (this.filter != null) { + return; + } + let testTypeFilter = 0; + let sizeFilter = 0; + let levelFilter = 0; + if (this.testType != null) { + testTypeFilter = this.testType.split(',') + .map(item => this.filterParam.testType[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.level != null) { + levelFilter = this.level.split(',') + .map(item => this.filterParam.level[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.size != null) { + sizeFilter = this.size.split(',') + .map(item => this.filterParam.size[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + this.filter = testTypeFilter | sizeFilter | levelFilter; + console.info(`${TAG}filter params:${this.filter}`); + } + + isCurrentSuite(description) { + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + let suiteArray = this.suite.split(','); + return suiteArray.indexOf(description) !== -1; + } + return false; + } + + filterSuite(currentSuiteName) { + let filterArray = []; + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, '', this.suite)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, '', this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, '', this.notClass)); + } + + let result = filterArray.map(item => item.filterSuite()).reduce((pre, cur) => pre || cur, false); + return result; + } + + filterDesc(currentSuiteName, desc, fi, coreContext) { + let filterArray = []; + if (this.itName !== undefined && this.itName !== '' && this.itName !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, desc, this.itName)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, desc, this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, desc, this.notClass)); + } + if (typeof (this.filter) !== 'undefined' && this.filter !== 0 && fi !== 0) { + filterArray.push(new TestTypesFilter('', '', fi, this.filter)); + } + let result = filterArray.map(item => item.filterIt()).reduce((pre, cur) => pre || cur, false); + return result; + } + + isRandom() { + return this.random || false; + } + + isBreakOnError() { + return this.breakOnError !== true ? false : true; + } + + setSupportAsync(value) { + this.supportAsync = value; + } + + isSupportAsync() { + return this.supportAsync; + } + + translateParams(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = {}; + for (const key in parameters) { + if (keySet.has(key)) { + var newKey = key.replace("-s ", ""); + targetParams[newKey] = parameters[key]; + } + } + return targetParams; + } + translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key]; + } + } + return targetParams.trim(); + } + + execute() { + } +} + +export { + ConfigService +}; diff --git a/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js b/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js new file mode 100644 index 0000000..632a682 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/coverage/coverageCollect.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "../kit/SysTestKit"; + +export async function collectCoverageData() { + if (globalThis.__coverage__ === undefined) { + return; + } + const strJson = JSON.stringify(globalThis.__coverage__); + const strLen = strJson.length; + const maxLen = 500; + const maxCount = Math.floor(strLen / maxLen); + const OHOS_REPORT_COVERAGE_DATA = 'OHOS_REPORT_COVERAGE_DATA:'; + for (let count = 0; count <= maxCount; count++) { + console.info(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); + await SysTestKit.print(`${OHOS_REPORT_COVERAGE_DATA} ${strJson.substring(count * maxLen, (count + 1) * maxLen)}`); + } +} \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js b/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js new file mode 100644 index 0000000..65d063c --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {TAG} from '../../Constant'; + +export default class SysTestKit { + + static delegator = null; + static systemTime = null; + + constructor() { + this.id = 'sysTestKit'; + this.index = 0; + } + + static actionStart(tag) { + console.info(`${TAG}${JSON.stringify(tag)}`); + var message = '\n' + 'OHOS_REPORT_ACTIONSTART: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(`${TAG}${JSON.stringify(tag)} actionStart print success`); + } + + static actionEnd(tag) { + console.info(`${TAG}${JSON.stringify(tag)}`); + var message = '\n' + 'OHOS_REPORT_ACTIONEND: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(`${TAG}${JSON.stringify(tag)} actionEnd print success`); + } + + static async existKeyword(keyword, timeout) { + let reg = new RegExp(/^[a-zA-Z0-9]{1,}$/); + if (!reg.test(keyword)) { + throw new Error('keyword must contain more than one string, and only letters and numbers are supported.'); + } + timeout = timeout || 4; + + let searchResult = false; + let cmd = 'hilog -x | grep -i \'' + keyword + '\' | wc -l'; + await executePromise(cmd, timeout).then((data) => { + searchResult = data; + }); + return searchResult; + } + static async print(message) { + if ('printSync' in SysTestKit.delegator) { + console.debug(`${TAG}printSync called ...`); + SysTestKit.delegator.printSync(message); + } else { + await SysTestKit.delegator.print(message); + } + } + + static async getRealTime() { + let currentTime = new Date().getTime(); + if (SysTestKit.systemTime !== null && SysTestKit.systemTime !== undefined) { + await SysTestKit.systemTime.getRealTime().then((time) => { + console.info(`${TAG}systemTime.getRealTime success data: ${JSON.stringify(time)}`); + currentTime = time; + }).catch((error) => { + console.error(`${TAG}failed to systemTime.getRealTime because ${JSON.stringify(error)}`); + }); + } + return currentTime; + } +} + +function executePromise(cmd, timeout) { + return new Promise((resolve, reject) => { + SysTestKit.delegator.executeShellCommand(cmd, timeout, + (error, data) => { + console.info(`${TAG}existKeyword CallBack: err : ${JSON.stringify(error)}`); + console.info(`${TAG}existKeyword CallBack: data : ${JSON.stringify(data)}`); + resolve(parseInt(data.stdResult) > 3 ? true : false); + }); + }); +} \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js b/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js new file mode 100644 index 0000000..6a9d7aa --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js b/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js new file mode 100644 index 0000000..c6a866a --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js b/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js new file mode 100644 index 0000000..1bd83be --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 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 = new Map(); + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + init() { + this.reset(); + } + + reset() { + this.mFunctions = []; + this.stubs = {}; + this.recordCalls = {}; + this.currentSetKey = new Map(); + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + clearAll() { + this.reset(); + var props = Object.keys(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + + var props = Object.getOwnPropertyNames(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + for (var key in this) { + delete this[key]; + } + } + + clear(obj) { + if (!obj) throw Error("Please enter an object to be cleaned"); + if (typeof (obj) != 'object') throw new Error('Not a object'); + this.recordMockedMethod.forEach(function (value, key, map) { + if (key) { + obj[key] = value; + } + }); + } + + ignoreMock(obj, method) { + if (typeof (obj) != 'object') throw new Error('Not a object'); + if (typeof (method) != 'function') throw new Error('Not a function'); + let og = this.recordMockedMethod.get(method.propName); + if (og) { + obj[method.propName] = og; + this.recordMockedMethod.set(method.propName, undefined); + } + } + + extend(dest, source) { + dest["stub"] = source["stub"]; + dest["afterReturn"] = source["afterReturn"]; + dest["afterReturnNothing"] = source["afterReturnNothing"]; + dest["afterAction"] = source["afterAction"]; + dest["afterThrow"] = source["afterThrow"]; + dest["stubMockedCall"] = source["stubMockedCall"]; + dest["clear"] = source["clear"]; + return dest; + } + + stubApply(f, params, returnInfo) { + let values = this.stubs.get(f); + if (!values) { + values = new Map(); + } + let key = params[0]; + if (typeof key == "undefined") { + key = "anonymous-mock-" + f.propName; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheStubKey(key)) { + key = matcher.matcheStubKey(key); + if (key) { + this.currentSetKey.set(f, key); + } + } + values.set(key, returnInfo); + this.stubs.set(f, values); + } + + getReturnInfo(f, params) { + let values = this.stubs.get(f); + if (!values) { + return undefined; + } + let retrunKet = params[0]; + if (typeof retrunKet == "undefined") { + retrunKet = "anonymous-mock-" + f.propName; + } + let stubSetKey = this.currentSetKey.get(f); + + if (stubSetKey && (typeof (retrunKet) != "undefined")) { + retrunKet = stubSetKey; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheReturnKey(params[0], undefined, stubSetKey) && matcher.matcheReturnKey(params[0], undefined, stubSetKey) != stubSetKey) { + retrunKet = params[0]; + } + + values.forEach(function (value, key, map) { + if (ArgumentMatchers.isRegExp(key) && matcher.matcheReturnKey(params[0], key)) { + retrunKet = key; + } + }); + + return values.get(retrunKet); + } + + findName(obj, value) { + let properties = this.findProperties(obj); + let name = null; + properties.filter(item => (item !== 'caller' && item !== 'arguments')).forEach( + function (va1, idx, array) { + if (obj[va1] === value) { + name = va1; + } + } + ); + return name; + } + + isFunctionFromPrototype(f, container, propName) { + if (container.constructor != Object && container.constructor.prototype !== container) { + return container.constructor.prototype[propName] === f; + } + return false; + } + + findProperties(obj, ...arg) { + function getProperty(new_obj) { + if (new_obj.__proto__ === null) { + return []; + } + let properties = Object.getOwnPropertyNames(new_obj); + return [...properties, ...getProperty(new_obj.__proto__)]; + } + return getProperty(obj); + } + + recordMethodCall(originalMethod, args) { + Function.prototype.getName = function () { + return this.name || this.toString().match(/function\s*([^(]*)\(/)[1]; + }; + let name = originalMethod.getName(); + let arglistString = name + '(' + Array.from(args).toString() + ')'; + let records = this.recordCalls.get(arglistString); + if (!records) { + records = 0; + } + records++; + this.recordCalls.set(arglistString, records); + } + + mockFunc(originalObject, originalMethod) { + let tmp = this; + this.originalMethod = originalMethod; + let f = function () { + let args = arguments; + let action = tmp.getReturnInfo(f, args); + if (originalMethod) { + tmp.recordMethodCall(originalMethod, args); + } + if (action) { + return action.apply(this, args); + } + }; + + f.container = null || originalObject; + f.original = originalMethod || null; + + if (originalObject && originalMethod) { + if (typeof (originalMethod) != 'function') throw new Error('Not a function'); + var name = this.findName(originalObject, originalMethod); + originalObject[name] = f; + this.recordMockedMethod.set(name, originalMethod); + f.propName = name; + f.originalFromPrototype = this.isFunctionFromPrototype(f.original, originalObject, f.propName); + } + f.mocker = this; + this.mFunctions.push(f); + this.extend(f, new ExtendInterface(this)); + return f; + } + + verify(methodName, argsArray) { + if (!methodName) { + throw Error("not a function name"); + } + let a = this.recordCalls.get(methodName + '(' + argsArray.toString() + ')'); + return new VerificationMode(a ? a : 0); + } + + mockObject(object) { + if (!object || typeof object === "string") { + throw Error(`this ${object} cannot be mocked`); + } + const _this = this; + let mockedObject = {}; + let keys = Reflect.ownKeys(object); + keys.filter(key => (typeof Reflect.get(object, key)) === 'function') + .forEach(key => { + mockedObject[key] = object[key]; + mockedObject[key] = _this.mockFunc(mockedObject, mockedObject[key]); + }); + return mockedObject; + } +} + +function ifMockedFunction(f) { + if (Object.prototype.toString.call(f) != "[object Function]" && + Object.prototype.toString.call(f) != "[object AsyncFunction]") { + throw Error("not a function"); + } + if (!f.stub) { + throw Error("not a mock function"); + } + return true; +} + +function when(f) { + if (ifMockedFunction(f)) { + return f.stub.bind(f); + } +} + +export {MockKit, when}; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js b/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js new file mode 100644 index 0000000..28eda2b --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {expect} from '../../interface'; + +class VerificationMode { + constructor(times) { + this.doTimes = times; + } + + times(count) { + expect(count).assertEqual(this.doTimes); + } + + never() { + console.log(this.doTimes); + expect(0).assertEqual(this.doTimes); + } + + once() { + expect(1).assertEqual(this.doTimes); + } + + atLeast(count) { + if (count > this.doTimes) { + throw Error('failed ' + count + ' greater than the actual execution times of method'); + } + } + + atMost(count) { + if (count < this.doTimes) { + throw Error('failed ' + count + ' less than the actual execution times of method'); + } + } +} + +export default VerificationMode; \ No newline at end of file diff --git a/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js b/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js new file mode 100644 index 0000000..f648b11 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "../kit/SysTestKit"; +import {collectCoverageData} from '../coverage/coverageCollect'; +import {TAG} from '../../Constant'; + +class OhReport { + constructor(attr) { + this.delegator = attr.delegator; + this.abilityDelegatorArguments = attr.abilityDelegatorArguments; + this.id = 'report'; + this.index = 0; + this.duration = 0; + } + + init(coreContext) { + this.coreContext = coreContext; + this.suiteService = this.coreContext.getDefaultService('suite'); + this.specService = this.coreContext.getDefaultService('spec'); + } + + taskStart() { + } + + async taskDone() { + if (this.abilityDelegatorArguments !== null) { + this.taskDoneTime = new Date().getTime(); + let summary = this.suiteService.getSummary(); + const configService = this.coreContext.getDefaultService('config'); + if (configService['coverage'] === 'true') { + await collectCoverageData(); + } + let message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure; + message += ', Error: ' + summary.error; + message += ', Pass: ' + summary.pass; + message += ', Ignore: ' + summary.ignore; + message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n'; + let isHasError = summary.failure > 0 || summary.error > 0; + let config = this.coreContext.getDefaultService('config'); + if (config.isBreakOnError() && isHasError) { + // 未执行全部说明 + message += '\n' + 'OHOS_REPORT_RESULT: breakOnError model, Stopping whole test suite if one specific test case failed or error' + '\n'; + } + message += 'OHOS_REPORT_STATUS: taskconsuming=' + summary.duration + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + } + console.info(`${TAG}report print success`); + this.delegator.finishTest('your test finished!!!', 0, () => { }); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + var value = this.coreContext.getDefaultService('config').filterValid; + var message = 'this param ' + value.join(',') + ' is invalid' + '\n'; + this.delegator.finishTest(message, 0, () => { + }); + } + } + + async suiteStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_SUM: ' + this.suiteService.getCurrentRunningSuite().getSpecsNum(); + message += '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.suiteService.getCurrentRunningSuite().description} suiteStart print success`); + } + } + + async suiteDone() { + if (this.abilityDelegatorArguments !== null) { + const currentRunningSuite = this.suiteService.getCurrentRunningSuite(); + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: suiteconsuming=' + this.suiteService.getCurrentRunningSuite().duration; + if (currentRunningSuite.hookError) { + message += '\n' + `OHOS_REPORT_STATUS: ${currentRunningSuite.hookError.message}`; + } + message += '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.suiteService.getCurrentRunningSuite().description} suiteDone print success`); + } + } + + async specStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.specService.currentRunningSpec.description} specStart start print success`); + } + } + + async specDone() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + let errorMsg = ''; + if (this.specService.currentRunningSpec.error) { + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -1' + '\n'; + } else if (this.specService.currentRunningSpec) { + if (this.specService.currentRunningSpec.fail) { + errorMsg = this.specService.currentRunningSpec.fail?.message; + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + errorMsg; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + errorMsg + '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -2' + '\n'; + } else { + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 0' + '\n'; + } + } else { + message += '\n'; + } + message += 'OHOS_REPORT_STATUS: consuming=' + this.specService.currentRunningSpec.duration + '\n'; + console.info(`${message}`); + await SysTestKit.print(message); + console.info(`${TAG}${this.specService.currentRunningSpec.description} specDone end print success`); + } + } +} + +export default OhReport; diff --git a/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js b/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js new file mode 100644 index 0000000..852fbcd --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/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/oh_modules/@ohos/hypium/src/main/service.js b/oh_modules/@ohos/hypium/src/main/service.js new file mode 100644 index 0000000..55d04a8 --- /dev/null +++ b/oh_modules/@ohos/hypium/src/main/service.js @@ -0,0 +1,966 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SysTestKit from "./module/kit/SysTestKit"; +import {TAG} from './Constant'; + +class AssertException extends Error { + constructor(message) { + super(); + this.name = "AssertException"; + this.message = message; + } +} + +function getFuncWithArgsZero(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + try { + await func(); + } catch (err) { + reject(err); + } + timer !== null ? clearTimeout(timer) : null; + resolve(); + }); +} + +function getFuncWithArgsOne(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout);; + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function getFuncWithArgsTwo(func, timeout, paramItem, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done, paramItem); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function processFunc(coreContext, func) { + let argNames = ((func || '').toString() + .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '') + .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2] + .split(',') // split parameters + .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim())) + .filter(String); + let funcLen = func.length; + let processedFunc; + const config = coreContext.getDefaultService('config'); + config.setSupportAsync(true); + const timeout = + (config.timeout === undefined ? 5000 : config.timeout); + const isStressTest = (coreContext.getServices('dataDriver') !== undefined || config.getStress() > 1); + switch (funcLen) { + case 0: { + processedFunc = function () { + return getFuncWithArgsZero(func, timeout, isStressTest); + }; + break; + } + case 1: { + if (argNames[0] === 'data') { + processedFunc = function (paramItem) { + func(paramItem); + }; + } else { + processedFunc = function () { + return getFuncWithArgsOne(func, timeout, isStressTest); + }; + } + break; + } + default: { + processedFunc = function (paramItem) { + return getFuncWithArgsTwo(func, timeout, paramItem, isStressTest); + }; + break; + } + } + return processedFunc; +} + +function secureRandomNumber() { + return crypto.randomBytes(8).readUInt32LE() / 0xffffffff; +} + +class SuiteService { + constructor(attr) { + this.id = attr.id; + this.rootSuite = new SuiteService.Suite({}); + this.currentRunningSuite = this.rootSuite; + this.suitesStack = [this.rootSuite]; + } + + describe(desc, func) { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterSuite(desc)) { + console.info(`${TAG}filter suite : ${desc}`); + return; + } + const suite = new SuiteService.Suite({description: desc}); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc); + for (let i = 1; i < suiteStress; i++) { + this.currentRunningSuite.childSuites.push(suite); + } + } + this.currentRunningSuite.childSuites.push(suite); + this.currentRunningSuite = suite; + this.suitesStack.push(suite); + func.call(); + let childSuite = this.suitesStack.pop(); + if (this.suitesStack.length === 0) { + this.currentRunningSuite = childSuite; + this.suitesStack.push(childSuite); + } + if (this.suitesStack.length > 1) { + this.currentRunningSuite = this.suitesStack.pop(); + } else { + this.currentRunningSuite = this.suitesStack.pop(); + this.suitesStack.push(this.currentRunningSuite); + } + } + + beforeAll(func) { + this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func)); + } + + beforeEach(func) { + this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func)); + } + + afterAll(func) { + this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func)); + } + + afterEach(func) { + this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func)); + } + + getCurrentRunningSuite() { + return this.currentRunningSuite; + } + + setCurrentRunningSuite(suite) { + this.currentRunningSuite = suite; + } + + traversalResults(suite, obj, breakOnError) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + for (const itItem of suite.specs) { + obj.total++; + if (breakOnError && (obj.error > 0 || obj.failure > 0)) { // breakOnError模式 + continue; + } + if (itItem.error) { + obj.error++; + } else if (itItem.fail) { + obj.failure++; + } else if (itItem.pass === true) { + obj.pass++; + } + } + } + + obj.duration += suite.duration; + + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + this.traversalResults(suiteItem, obj, breakOnError); + } + } + } + + async setSuiteResults(suite, error, coreContext) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + const specService = coreContext.getDefaultService('spec'); + for (const specItem of suite.specs) { + specService.setCurrentRunningSpec(specItem); + if (error instanceof AssertException) { + specItem.fail = error; + } else { + specItem.error = error; + } + await coreContext.fireEvents('spec', 'specStart', specItem); + await coreContext.fireEvents('spec', 'specDone', specItem); + } + } + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + await this.setSuiteResults(suiteItem, error, coreContext); + } + } + } + + getSummary() { + let suiteService = this.coreContext.getDefaultService('suite'); + let rootSuite = suiteService.rootSuite; + const specService = this.coreContext.getDefaultService('spec'); + const configService = this.coreContext.getDefaultService('config'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + let isBreaKOnError = breakOnError && isError; + let obj = {total: 0, failure: 0, error: 0, pass: 0, ignore: 0, duration: 0}; + for (const suiteItem of rootSuite.childSuites) { + this.traversalResults(suiteItem, obj, isBreaKOnError); + } + obj.ignore = obj.total - obj.pass - obj.failure - obj.error; + return obj; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + traversalSuites(suite, obj, configService) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return []; + } + if (suite.specs.length > 0) { + let itArray = []; + for (const itItem of suite['specs']) { + if (!configService.filterDesc(suite.description, itItem.description, itItem.fi, null)) { + itArray.push({'itName': itItem.description}); + } + } + obj[suite.description] = itArray; + } + + if (suite.childSuites.length > 0) { + let suiteArray = []; + for (const suiteItem of suite.childSuites) { + let suiteObj = {}; + this.traversalSuites(suiteItem, suiteObj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suiteArray.push(suiteObj); + } + } + obj.suites = suiteArray; + } + } + + async dryRun(abilityDelegator) { + const configService = this.coreContext.getDefaultService('config'); + let testSuitesObj = {}; + let suitesArray = []; + for (const suiteItem of this.rootSuite.childSuites) { + let obj = {}; + this.traversalSuites(suiteItem, obj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suitesArray.push(obj); + } + } + testSuitesObj['suites'] = suitesArray; + + let strJson = JSON.stringify(testSuitesObj); + let strLen = strJson.length; + let maxLen = 500; + let maxCount = Math.floor(strLen / maxLen); + + for (let count = 0; count <= maxCount; count++) { + await SysTestKit.print(strJson.substring(count * maxLen, (count + 1) * maxLen)); + } + console.info(`${TAG}dryRun print success`); + abilityDelegator.finishTest('dry run finished!!!', 0, () => { }); + } + + execute() { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterValid.length !== 0) { + this.coreContext.fireEvents('task', 'incorrectFormat'); + return; + } + + if (configService.isRandom() && this.rootSuite.childSuites.length > 0) { + this.rootSuite.childSuites.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + this.currentRunningSuite = this.rootSuite.childSuites[0]; + } + + if (configService.isSupportAsync()) { + let asyncExecute = async () => { + await this.coreContext.fireEvents('task', 'taskStart'); + await this.rootSuite.asyncRun(this.coreContext); + }; + asyncExecute().then(async () => { + await this.coreContext.fireEvents('task', 'taskDone'); + }); + } else { + this.coreContext.fireEvents('task', 'taskStart'); + this.rootSuite.run(this.coreContext); + this.coreContext.fireEvents('task', 'taskDone'); + } + } + + apis() { + const _this = this; + return { + describe: function (desc, func) { + return _this.describe(desc, func); + }, + beforeAll: function (func) { + return _this.beforeAll(func); + }, + beforeEach: function (func) { + return _this.beforeEach(func); + }, + afterAll: function (func) { + return _this.afterAll(func); + }, + afterEach: function (func) { + return _this.afterEach(func); + } + }; + } +} + +SuiteService.Suite = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.childSuites = []; + this.specs = []; + this.beforeAll = []; + this.afterAll = []; + this.beforeEach = []; + this.afterEach = []; + this.duration = 0; + this.hookError = null; + } + + pushSpec(spec) { + this.specs.push(spec); + } + + removeSpec(desc) { + this.specs = this.specs.filter((item, index) => { + return item.description !== desc; + }); + } + + getSpecsNum() { + return this.specs.length; + } + + isRun(coreContext) { + const configService = coreContext.getDefaultService('config'); + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + return breakOnError && isError; + } + + run(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteStart', this); + } + this.runHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + for (let spec in this.specs) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + this.runHookFunc('beforeEach'); + spec.run(coreContext); + this.runHookFunc('afterEach'); + } + } + if (this.childSuites.length > 0) { + for (let suite in this.childSuites) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + suite.run(coreContext); + suiteService.setCurrentRunningSuite(suite); + } + } + this.runHookFunc('afterAll'); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteDone'); + } + } + + async asyncRunSpecs(coreContext) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + const specService = coreContext.getDefaultService('spec'); + for (let specItem of this.specs) { + specService.setCurrentRunningSpec(specItem); + // 遇错即停模式,发现用例有问题,直接返回,不在执行后面的it + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log("break description :" + this.description); + break; + } + await coreContext.fireEvents('spec', 'specStart', specItem); + try { + await this.runAsyncHookFunc('beforeEach'); + await specItem.asyncRun(coreContext); + await this.runAsyncHookFunc('afterEach'); + } catch (e) { + console.error(`${TAG}${e?.stack}`); + if (e instanceof AssertException) { + specItem.fail = e; + } else { + specItem.error = e; + } + specService.setStatus(true); + } + specItem.setResult(); + await coreContext.fireEvents('spec', 'specDone', specItem); + specService.setCurrentRunningSpec(null); + } + } + + async asyncRunChildSuites(coreContext) { + for (let i = 0; i < this.childSuites.length; i++) { + // 遇错即停模式, 发现用例有问题,直接返回,不在执行后面的description + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log(`${TAG}break description : ${this.description}`); + break; + } + await this.childSuites[i].asyncRun(coreContext); + } + } + + async asyncRun(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + + suiteService.setCurrentRunningSuite(this); + suiteService.suitesStack.push(this); + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteStart', this); + } + + try { + await this.runAsyncHookFunc('beforeAll'); + } catch (error) { + console.error(`${TAG}${error?.stack}`); + this.hookError = error; + } + + if (this.hookError !== null) { + specService.setStatus(true); + await suiteService.setSuiteResults(this, this.hookError, coreContext); + } + + if (this.specs.length > 0 && this.hookError === null) { + await this.asyncRunSpecs(coreContext); + } + + if (this.childSuites.length > 0 && this.hookError === null) { + await this.asyncRunChildSuites(coreContext); + } + + try { + await this.runAsyncHookFunc('afterAll'); + } catch (error) { + console.error(`${TAG}${error?.stack}`); + this.hookError = error; + specService.setStatus(true); + } + + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteDone'); + let childSuite = suiteService.suitesStack.pop(); + if (suiteService.suitesStack.length === 0) { + suiteService.suitesStack.push(childSuite); + } + if (suiteService.suitesStack.length > 1) { + suiteService.setCurrentRunningSuite(suiteService.suitesStack.pop()); + } else { + let currentRunningSuite = suiteService.suitesStack.pop(); + suiteService.setCurrentRunningSuite(currentRunningSuite); + suiteService.suitesStack.push(currentRunningSuite); + } + } + } + + runHookFunc(hookName) { + if (this[hookName] && this[hookName].length > 0) { + this[hookName].forEach(func => { + try { + func(); + } catch (e) { + console.error(`${TAG}${e.stack}`); + } + }); + } + } + + async runAsyncHookFunc(hookName) { + for (const hookItem of this[hookName]) { + try { + await hookItem(); + } catch (error) { + error['message'] += `, error in ${hookName} function`; + throw error; + } + + } + } +}; + +class SpecService { + constructor(attr) { + this.id = attr.id; + this.totalTest = 0; + this.hasError = false; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + setCurrentRunningSpec(spec) { + this.currentRunningSpec = spec; + } + + setStatus(obj) { + this.hasError = obj; + } + + getStatus() { + return this.hasError; + } + + getTestTotal() { + return this.totalTest; + } + + getCurrentRunningSpec() { + return this.currentRunningSpec; + } + + it(desc, filter, func) { + const configService = this.coreContext.getDefaultService('config'); + const currentSuiteName = this.coreContext.getDefaultService('suite').getCurrentRunningSuite().description; + if (configService.filterDesc(currentSuiteName, desc, filter, this.coreContext)) { + console.info(`${TAG}filter it :${desc}`); + } else { + let processedFunc = processFunc(this.coreContext, func); + const spec = new SpecService.Spec({description: desc, fi: filter, fn: processedFunc}); + const suiteService = this.coreContext.getDefaultService('suite'); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc); + for (let i = 1; i < specStress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + // dryRun 状态下不统计压力测试重复数据 + if (configService['dryRun'] !== 'true') { + let stress = configService.getStress(); // 命令配置压力测试 + console.info(`${TAG}stress length : ${stress}`); + for (let i = 1; i < stress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + apis() { + const _this = this; + return { + it: function (desc, filter, func) { + return _this.it(desc, filter, func); + } + }; + } +} + +SpecService.Spec = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.fi = attrs.fi; + this.fn = attrs.fn || function () { + }; + this.fail = undefined; + this.error = undefined; + this.duration = 0; + this.startTime = 0; + this.isExecuted = false; // 当前用例是否执行 + } + + setResult() { + if (this.fail) { + this.pass = false; + } else { + this.pass = true; + } + } + + run(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + coreContext.fireEvents('spec', 'specStart', this); + this.isExecuted = true; + try { + let dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + this.fn(); + } else { + let suiteParams = dataDriver.dataDriver.getSuiteParams(); + let specParams = dataDriver.dataDriver.getSpecParams(); + console.info(`${TAG}[suite params] ${JSON.stringify(suiteParams)}`); + console.info(`${TAG}[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; + specService.setStatus(true); + } + coreContext.fireEvents('spec', 'specDone', this); + } + + async asyncRun(coreContext) { + const dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + await this.fn(); + } else { + const suiteParams = dataDriver.dataDriver.getSuiteParams(); + const specParams = dataDriver.dataDriver.getSpecParams(); + console.info(`[suite params] ${JSON.stringify(suiteParams)}`); + console.info(`[spec params] ${JSON.stringify(specParams)}`); + if (this.fn.length === 0) { + await this.fn(); + } else if (specParams.length === 0) { + await this.fn(suiteParams); + } else { + for (const paramItem of specParams) { + await this.fn(Object.assign({}, paramItem, suiteParams)); + } + } + } + + this.isExecuted = true; + } + + filterCheck(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + return true; + } +}; + +class ExpectService { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + expect(actualValue) { + return this.wrapMatchers(actualValue); + } + + init(coreContext) { + this.coreContext = coreContext; + this.addMatchers(this.basicMatchers()); + } + + addMatchers(matchers) { + for (const matcherName in matchers) { + if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) { + this.matchers[matcherName] = matchers[matcherName]; + } + } + } + + basicMatchers() { + return { + assertTrue: function (actualValue) { + return { + pass: (actualValue) === true, + message: 'expect true, actualValue is ' + actualValue + }; + }, + assertEqual: function (actualValue, args) { + return { + pass: (actualValue) === args[0], + expectValue: args[0], + message: 'expect ' + actualValue + ' equals ' + args[0] + }; + }, + assertThrow: function (actual, args) { + const result = { + pass: false + }; + if (typeof actual !== 'function') { + result.message = 'toThrow\'s Actual should be a Function'; + } else { + let hasThrow = false; + let throwError; + try { + actual(); + } catch (e) { + hasThrow = true; + throwError = e; + } + if (!hasThrow) { + result.message = 'function did not throw an exception'; + } else if (throwError && throwError.message === args[0]) { + result.pass = true; + } else { + result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`; + } + } + return result; + } + }; + } + + wrapMatchers(actualValue) { + const _this = this; + const wrappedMatchers = { + // 翻转标识 + isNot: false, + + // 翻转方法 + not: function () { + this.isNot = true; + return this; + } + }; + const specService = _this.coreContext.getDefaultService('spec'); + const currentRunningSpec = specService.getCurrentRunningSpec(); + const currentRunningSuite = _this.coreContext.getDefaultService('suite').getCurrentRunningSuite(); + for (const matcherName in this.matchers) { + let result = Object.prototype.hasOwnProperty.call(this.matchers, matcherName); + if (!result) { + continue; + } + if (matcherName.search('assertPromise') == 0) { + wrappedMatchers[matcherName] = async function () { + await _this.matchers[matcherName](actualValue, arguments).then(function (result) { + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + const assertError = new AssertException(result.message); + currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError; + throw assertError; + } + }); + }; + } else { + wrappedMatchers[matcherName] = function () { + const result = _this.matchers[matcherName](actualValue, arguments); + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + const assertError = new AssertException(result.message); + currentRunningSpec ? currentRunningSpec.fail = assertError : currentRunningSuite.hookError = assertError; + throw assertError; + } + }; + } + } + return wrappedMatchers; + } + + apis() { + const _this = this; + return { + expect: function (actualValue) { + return _this.expect(actualValue); + } + }; + } +} + +class ReportService { + constructor(attr) { + this.id = attr.id; + } + + init(coreContext) { + this.coreContext = coreContext; + this.specService = this.coreContext.getDefaultService('spec'); + this.suiteService = this.coreContext.getDefaultService('suite'); + this.duration = 0; + } + + taskStart() { + console.info(`${TAG}[start] start run suites`); + } + + async suiteStart() { + console.info(`${TAG}[suite start]${this.suiteService.getCurrentRunningSuite().description}`); + } + + async specStart() { + console.info(`${TAG}start running case '${this.specService.currentRunningSpec.description}'`); + this.index = this.index + 1; + let spec = this.specService.currentRunningSpec; + spec.startTime = await SysTestKit.getRealTime(); + } + + async specDone() { + let msg = ''; + let spec = this.specService.currentRunningSpec; + let suite = this.suiteService.currentRunningSuite; + spec.duration = await SysTestKit.getRealTime() - spec.startTime; + suite.duration += spec.duration; + if (spec.error) { + this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('errorDetail', spec.error); + } else if (spec.fail) { + this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('failDetail', spec.fail?.message); + } else { + this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms'); + } + this.formatPrint(this.specService.currentRunningSpec.error, msg); + } + + suiteDone() { + let suite = this.suiteService.currentRunningSuite; + let message = suite.hookError ? `, ${suite.hookError?.message}` : ''; + console.info(`[suite end] ${suite.description} consuming ${suite.duration} ms${message}`); + } + + taskDone() { + let msg = ''; + let summary = this.suiteService.getSummary(); + msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error; + msg += ',pass ' + summary.pass + '; consuming ' + summary.duration + 'ms'; + console.info(`${TAG}${msg}`); + console.info(`${TAG}[end] run suites end`); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + this.coreContext.getDefaultService('config').filterValid.forEach(function (item) { + console.info(`${TAG}this param ${item} is invalid`); + }); + } + } + + formatPrint(type, msg) { + switch (type) { + case 'pass': + console.info(`${TAG}[pass]${msg}`); + break; + case 'fail': + console.info(`${TAG}[fail]${msg}`); + break; + case 'failDetail': + console.info(`${TAG}[failDetail]${msg}`); + break; + case 'error': + console.info(`${TAG}[error]${msg}`); + break; + case 'errorDetail': + console.info(`${TAG}[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 +}; diff --git a/product/phone/oh-package-lock.json5 b/product/phone/oh-package-lock.json5 new file mode 100644 index 0000000..545f332 --- /dev/null +++ b/product/phone/oh-package-lock.json5 @@ -0,0 +1,25 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/common@../../common": "@ohos/common@../../common", + "@ohos/recorder@../../feature/recorder": "@ohos/recorder@../../feature/recorder" + }, + "packages": { + "@ohos/common@../../common": { + "name": "@ohos/common", + "version": "1.0.0", + "resolved": "../../common", + "registryType": "local" + }, + "@ohos/recorder@../../feature/recorder": { + "name": "@ohos/recorder", + "version": "1.0.0", + "resolved": "../../feature/recorder", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/product/phone/oh-package.json5 b/product/phone/oh-package.json5 new file mode 100644 index 0000000..19035eb --- /dev/null +++ b/product/phone/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "devDependencies": {}, + "name": "phone", + "description": "example description", + "version": "1.0.0", + "dynamicDependencies": {}, + "dependencies": { + "@ohos/recorder": "file:../../feature/recorder", + "@ohos/common": "file:../../common" + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/.gitignore b/product/phone/oh_modules/@ohos/common/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/BuildProfile.ets b/product/phone/oh_modules/@ohos/common/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/build-profile.json5 b/product/phone/oh_modules/@ohos/common/build-profile.json5 new file mode 100644 index 0000000..7374b5c --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/build-profile.json5 @@ -0,0 +1,17 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + } + } + } + }, + ] +} diff --git a/product/phone/oh_modules/@ohos/common/hvigorfile.js b/product/phone/oh_modules/@ohos/common/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/product/phone/oh_modules/@ohos/common/index.ets b/product/phone/oh_modules/@ohos/common/index.ets new file mode 100644 index 0000000..af9c605 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/index.ets @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { default as ConfigData } from './src/main/ets/utils/ConfigData' + +export { default as Util } from './src/main/ets/utils/Util' + +export { default as LogUtil } from './src/main/ets/utils/LogUtil' diff --git a/product/phone/oh_modules/@ohos/common/oh-package.json5 b/product/phone/oh_modules/@ohos/common/oh-package.json5 new file mode 100644 index 0000000..3159c13 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "index.ets", + "version": "1.0.0", +} diff --git a/product/phone/oh_modules/@ohos/common/package.json b/product/phone/oh_modules/@ohos/common/package.json new file mode 100644 index 0000000..dfbf6f7 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/hap": "^3.0.0" + } +} diff --git a/product/phone/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets b/product/phone/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets new file mode 100644 index 0000000..728136a --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 class ConfigData { + WH_100_100 = '100%'; + WH_50_100 = '50%'; + WH_40_100 = '40%'; + WH_20_100 = '20%'; +} + +let configData = new ConfigData(); + +export default configData as ConfigData; \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts b/product/phone/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts new file mode 100644 index 0000000..bbead9d --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 HiLog from "@ohos.hilog"; + +const DOMAIN = 0x0500; +const TAG = "[Recorder]"; + +/** + * log package tool class + */ +export default class LogUtil { + static debug(msg): void { + HiLog.debug(DOMAIN, TAG, msg); + } + + static log(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static info(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static warn(msg): void { + HiLog.warn(DOMAIN, TAG, msg); + } + + static error(msg): void { + HiLog.error(DOMAIN, TAG, msg); + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/ets/utils/Util.ets b/product/phone/oh_modules/@ohos/common/src/main/ets/utils/Util.ets new file mode 100644 index 0000000..d7ff070 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/ets/utils/Util.ets @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 default class Util { + + /** + * Time format is converted to seconds + * + * @param timestamp + * @param hasHour + */ + static timeFormat(timestamp: number, hasHour: boolean = true): string { + if (timestamp < 0) { + return ""; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hasHour || hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + return timeStr; + } + + /** + * Time format is converted to milliseconds + * + * @param timestamp + */ + static timeFormatMs(timestamp: number): string { + if (timestamp <= 0) { + return "00:00.00"; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + if (hour < 1) { + let mSec = Math.floor(timestamp % 1000 / 10); + timeStr += "." + Util.addZero(mSec); + } + return timeStr; + } + + /** + * Gets the date at the specified time + * + * @param date + */ + static getDateFormat(date: number): string { + let nowDate = new Date(date); + return nowDate.getFullYear() + "/" + Util.addZero(nowDate.getMonth() + 1) + "/" + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the specified time + * + * @param date + */ + static getTimeFormat(date: number): string { + let nowDate = new Date(date); + return Util.addZero(nowDate.getHours()) + ":" + Util.addZero(nowDate.getMinutes()) + ":" + Util.addZero(nowDate.getSeconds()); + } + + /** + * Gets the current time date + */ + static getDate(): string { + let nowDate = new Date(); + return nowDate.getFullYear() + Util.addZero(nowDate.getMonth() + 1) + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the current time + */ + static getTime(): string { + let nowDate = new Date(); + return Util.addZero(nowDate.getHours()) + Util.addZero(nowDate.getMinutes()) + Util.addZero(nowDate.getSeconds()); + } + + /** + * If the number is less than 10, add "0". + * + * @param num + */ + static addZero(num: number): string{ + return (num < 10 ? "0" + num : num).toString(); + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/module.json5 b/product/phone/oh_modules/@ohos/common/src/main/module.json5 new file mode 100644 index 0000000..56a91a8 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "common", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/element/color.json b/product/phone/oh_modules/@ohos/common/src/main/resources/base/element/color.json new file mode 100644 index 0000000..ffe7272 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/element/color.json @@ -0,0 +1,32 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "background_color", + "value": "#F1F3F5" + }, + { + "name": "shadow_color", + "value": "#11000000" + }, + { + "name": "pointer_color", + "value": "#007DFF" + }, + { + "name": "warn_color", + "value": "#FF595A" + }, + { + "name": "hint_color", + "value": "#007DFF" + }, + { + "name": "text_color", + "value": "#182431" + } + ] +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/element/string.json b/product/phone/oh_modules/@ohos/common/src/main/resources/base/element/string.json new file mode 100644 index 0000000..2375b2d --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + }, + { + "name": "title", + "value": "录音机" + }, + { + "name": "search_recording_files", + "value": "搜索录音文件" + }, + { + "name": "mark", + "value": "标记" + }, + { + "name": "pause", + "value": "暂停" + }, + { + "name": "continue_record", + "value": "继续" + }, + { + "name": "predict_hint", + "value": "预计还能录制10小时以上" + }, + { + "name": "delete_hint", + "value": "是否删除此条录音?" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "delete", + "value": "删除" + }, + { + "name": "has_call_hint", + "value": "通话状态无法录音" + }, + { + "name": "recording_hint", + "value": "录音机正在录音" + }, + { + "name": "suspend_record_hint", + "value": "录音机暂停录音" + } + ] +} diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png new file mode 100644 index 0000000000000000000000000000000000000000..41c12ccb5bb90cd9c05508690ca0b88f33e96008 GIT binary patch literal 3806 zcmdUx2~bnl8pm&BS5adC7Z5~>5L6UdB&-z>DkwaWML?iHA+kjRN!X!QL|N6MD42i* zNkBA$VGZKKs>CG5Kp=!Q2m}Zqpe(Yaw4Kf?4?EMD&YOAf+&Oda{hxFHzwbNe%$-lz zA?yRTSzDg81VA7F0IgntkPDcvzWuZItI0oeSp8b~5&%mAG!R?_v=7(-28n<{!UjNL zHAs=)yn#O&NJ3IfN>qH~>ZsMW)g(ZoBAXyZ@uqj(tb9cd2}%YL;=kX=>GI_v(WDiur@FdIyO~h>DA> zj+uj3V~`L7ZIY4%iTys|SBMx`SzJQv_!+P5vPX5Cypiae*en8CO-cj|m;x(r0hB`DpGdzydeLHr7k|tdD79%Ir8U)OFEHjn z#?9V$lHBFfY$ON36BN%Huf&2#lO&3rFDc%@Eo1|q`t3TKuLwtmo`)^Jv_p0j@SH6N z)^Z9Gkk{ti4|kW;+ds>-=vI5$Zi+ip1w#4W|BBH%X=j)xY^6`FN?<>AARk$>hGSo+ z-w;i@GtuEy6u*s<> z3p&#JM2&guq@bKJY=Z#YcU}03(>h6fcYCK_e4#kV`MI+U>rzDVDUQXNPY1Hga83SY z5B-wLk_EivBD{JTAt}Y}^mK|fzNOf><*zpcDg;haPTz4IN(EEhLbAuwp^u7w+V;1j zQD~>fS4mA6$~?2?cLl9YyR{@;OL44Vv0`U{a|Zw3gIU+%nSx3{Gqr48R-1eMuSNC4 zXgFTB4-MBeXu4-KW|@)5+NS&E(cEL@a3bRECv*!Yz9V-ym%bdo!^dcj;={p)TSvT@ zg$kCrKPPh>Rn?7PLHY=R98Ia(BHv&*)6eWFJ1J_v#>$gr`3lFQi{w`^fq2N2shIzh z2pnuO%4yi{;bYm*$!Ql(oAy|YT=rB-hIZ{pxBMwo8(vcz%*Ow&xCSV_9R= z(g)s>T|SXyf+$ctNJ+}xd*sATTLl;`o(rAGf}2X!XThVteXdnVIg-=AFzyn93P@o4 zlN@qVac^ne|u25+A1zJ4u=O8po*_yqlk%Z_Xbbp4-P5 zUE%a`5ip~yHjCaYcPnEg$zK0(gu^}#e}@{KD~UDN~t7S7SeUC=?t z1gjRFIAh#^+5f0YC%+EjLiC0jz3umZR8vF@&e=P9TWhx5yI+g@GK0$+T3yw83cCn5 zwjF&mC-t*azjmJ^oZP|ca!;M<8M*Fci6nI zjOA7~Y&<4gzA?AliO65L#$h&cW|m@4qZ>P}pRjW`h3UV5@JGh3-z&251)bd_8(zE* zYbXof(HsVyz=q{EJ7B3U-?hwlazm0-AziMoM_*JVW$?DA`a_jva{NsD)3{miWlnt; zB?1>ho$l0!V|v+a#g#2pao8Zm|J=Ff&tqOzOJf$|u8?8WR@EFLP0s8vbyMV0lPT>p zBbB0&p%l_I&UlP9S&~OC>!t7NuKrBE%0W#TS`99QnO^>W3Zue2+ipj2lcAZlPJ z*JSVc#G1&!p+i}8`=!KpDatzsuRMD|oUb#r-J(AIW}XDq5(1kMT~yNvy5bN=nBW#~%7*UeLr8QKJ&yG;En(eXf%qa9GzJ zQDN}P$As4%gV$`2sHNTN;nh)F2u&I(yPjP{O|pDs4oOW@|8e~-MMxD zSPA*dg}73S&nL8db6=SpKNZ?AK9cN{QQBb}i9$EnMfJwI22^;A({(w#D;~3CrewV> zf}Yc0?VyiUvZUQJ8JCaEeWPZ@Vpg`F-qI6&l*8FIJDq1Z`u?`t;jvHLiR0>t^!+A;Y`#FOnC&;eUzJ`!bTpW%#)ns+jaRsKvV47yB;9-HUy#x{Zy( zA7$MmYs{h)5L@t=Mo60sBQ9QaK}?GZsU$$tZJWJdgUoiYF~8R-`|+Kcury3Wo_r_6 zLPZ)@V-O97{)-n9E3X%{SQb1R{|!#b&a&5C$1qYrh5rEOwpa|B_|Fpmg6HvHP6$MAVKP4$llI;+cX@w}YKwSV%z1~5Fi7Ic*g2dvURZ*BkZC?>+jExyGu)Ffe8=j% z#a#Zs4@$ztK;vzxIzxgHfklD2^jN{IbBOV-WjHu9LN}#t+9E!CF3*1^NC@Orb;NrH zW_5r5(J9&_Oq@DKgifu!II_h5K>cF_2~_YWUc9@r8%Y}zF{w!r12*j3$`+=&g*>5YfC zQ;zM<1UIR4qh4U@rLCu9A*dYc`4v<}pBOXq$Mrtzm9=&8TF(DO{VnzmC}{k9eVX;> zy8Kyn(<42$yYjM2$k|iwQ`+ZrViRw^i;{3d80ghCv5WUe-!C`ok0@bfUk@ee;BX3? zNNs$aYA_*iI%;2XdCJKX;cg!qWf|p+V*r9#LwjIug}$42E4D^g&c-s>q-`TipKQiA zOR{$8R>!A>A8?cmxN>%`&0UiFBvEEq`chYh)j6_yhSk{pE5=4zenYdPv7twPQ(mb;I9 literal 0 HcmV?d00001 diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg new file mode 100644 index 0000000..6f7f039 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg @@ -0,0 +1,10 @@ + + + systemicon/back + + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg new file mode 100644 index 0000000..3ec94e4 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg @@ -0,0 +1,8 @@ + + + ic_clock_add + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg new file mode 100644 index 0000000..14a0ba5 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg @@ -0,0 +1,10 @@ + + + ic_clock_enhance + + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg new file mode 100644 index 0000000..330eda7 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg @@ -0,0 +1,8 @@ + + + ic_clock_mark + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg new file mode 100644 index 0000000..4a6c569 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg @@ -0,0 +1,7 @@ + + + ic_clock_play + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg new file mode 100644 index 0000000..c8f7906 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg @@ -0,0 +1,7 @@ + + + ic_clock_record + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg new file mode 100644 index 0000000..0296449 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg @@ -0,0 +1,7 @@ + + + ic_clock_stop + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg new file mode 100644 index 0000000..bf6f0ea --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg @@ -0,0 +1,8 @@ + + + ic_clock_suspend + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg new file mode 100644 index 0000000..34c0e94 --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg @@ -0,0 +1,8 @@ + + + ic_record_play + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg new file mode 100644 index 0000000..1b2a8aa --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg @@ -0,0 +1,8 @@ + + + ic_record_search + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg new file mode 100644 index 0000000..2b7ceaa --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg @@ -0,0 +1,9 @@ + + + ic_record_stop + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg new file mode 100644 index 0000000..400c3ef --- /dev/null +++ b/product/phone/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg @@ -0,0 +1,13 @@ + + + public_more + + + + + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/.gitignore b/product/phone/oh_modules/@ohos/recorder/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/BuildProfile.ets b/product/phone/oh_modules/@ohos/recorder/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/build-profile.json5 b/product/phone/oh_modules/@ohos/recorder/build-profile.json5 new file mode 100644 index 0000000..35dff6d --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/build-profile.json5 @@ -0,0 +1,5 @@ +{ + "apiType": "stageMode", + "buildOption": { + } +} diff --git a/product/phone/oh_modules/@ohos/recorder/hvigorfile.js b/product/phone/oh_modules/@ohos/recorder/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/product/phone/oh_modules/@ohos/recorder/index.ets b/product/phone/oh_modules/@ohos/recorder/index.ets new file mode 100644 index 0000000..98c6430 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/index.ets @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { RecordController, RecordState } from './src/main/ets/controller/RecordController' + +export { default as MediaController } from './src/main/ets/controller/MediaController' + +export { AudioController, AudioState } from './src/main/ets/controller/AudioController' + +export { StateController, ControlState } from './src/main/ets/controller/StateController' + +export { RecordData } from './src/main/ets/model/RecordData' diff --git a/product/phone/oh_modules/@ohos/recorder/oh-package-lock.json5 b/product/phone/oh_modules/@ohos/recorder/oh-package-lock.json5 new file mode 100644 index 0000000..71fb2aa --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh-package-lock.json5 @@ -0,0 +1,18 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/common@../../common": "@ohos/common@../../common" + }, + "packages": { + "@ohos/common@../../common": { + "name": "@ohos/common", + "version": "1.0.0", + "resolved": "../../common", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh-package.json5 b/product/phone/oh_modules/@ohos/recorder/oh-package.json5 new file mode 100644 index 0000000..c395a28 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh-package.json5 @@ -0,0 +1,13 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": { + "@ohos/common": "file:../../common" + }, + "name": "@ohos/recorder", + "description": "a npm package which contains arkUI2.0 page", + "main": "index.ets", + "version": "1.0.0", + "dynamicDependencies": {}, + "dependencies": {} +} diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 new file mode 100644 index 0000000..7374b5c --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 @@ -0,0 +1,17 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + } + } + } + }, + ] +} diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets new file mode 100644 index 0000000..af9c605 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { default as ConfigData } from './src/main/ets/utils/ConfigData' + +export { default as Util } from './src/main/ets/utils/Util' + +export { default as LogUtil } from './src/main/ets/utils/LogUtil' diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 new file mode 100644 index 0000000..3159c13 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "index.ets", + "version": "1.0.0", +} diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json new file mode 100644 index 0000000..dfbf6f7 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/hap": "^3.0.0" + } +} diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets new file mode 100644 index 0000000..728136a --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 class ConfigData { + WH_100_100 = '100%'; + WH_50_100 = '50%'; + WH_40_100 = '40%'; + WH_20_100 = '20%'; +} + +let configData = new ConfigData(); + +export default configData as ConfigData; \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts new file mode 100644 index 0000000..bbead9d --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 HiLog from "@ohos.hilog"; + +const DOMAIN = 0x0500; +const TAG = "[Recorder]"; + +/** + * log package tool class + */ +export default class LogUtil { + static debug(msg): void { + HiLog.debug(DOMAIN, TAG, msg); + } + + static log(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static info(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static warn(msg): void { + HiLog.warn(DOMAIN, TAG, msg); + } + + static error(msg): void { + HiLog.error(DOMAIN, TAG, msg); + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets new file mode 100644 index 0000000..d7ff070 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 default class Util { + + /** + * Time format is converted to seconds + * + * @param timestamp + * @param hasHour + */ + static timeFormat(timestamp: number, hasHour: boolean = true): string { + if (timestamp < 0) { + return ""; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hasHour || hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + return timeStr; + } + + /** + * Time format is converted to milliseconds + * + * @param timestamp + */ + static timeFormatMs(timestamp: number): string { + if (timestamp <= 0) { + return "00:00.00"; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + if (hour < 1) { + let mSec = Math.floor(timestamp % 1000 / 10); + timeStr += "." + Util.addZero(mSec); + } + return timeStr; + } + + /** + * Gets the date at the specified time + * + * @param date + */ + static getDateFormat(date: number): string { + let nowDate = new Date(date); + return nowDate.getFullYear() + "/" + Util.addZero(nowDate.getMonth() + 1) + "/" + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the specified time + * + * @param date + */ + static getTimeFormat(date: number): string { + let nowDate = new Date(date); + return Util.addZero(nowDate.getHours()) + ":" + Util.addZero(nowDate.getMinutes()) + ":" + Util.addZero(nowDate.getSeconds()); + } + + /** + * Gets the current time date + */ + static getDate(): string { + let nowDate = new Date(); + return nowDate.getFullYear() + Util.addZero(nowDate.getMonth() + 1) + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the current time + */ + static getTime(): string { + let nowDate = new Date(); + return Util.addZero(nowDate.getHours()) + Util.addZero(nowDate.getMinutes()) + Util.addZero(nowDate.getSeconds()); + } + + /** + * If the number is less than 10, add "0". + * + * @param num + */ + static addZero(num: number): string{ + return (num < 10 ? "0" + num : num).toString(); + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 new file mode 100644 index 0000000..56a91a8 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "common", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json new file mode 100644 index 0000000..ffe7272 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json @@ -0,0 +1,32 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "background_color", + "value": "#F1F3F5" + }, + { + "name": "shadow_color", + "value": "#11000000" + }, + { + "name": "pointer_color", + "value": "#007DFF" + }, + { + "name": "warn_color", + "value": "#FF595A" + }, + { + "name": "hint_color", + "value": "#007DFF" + }, + { + "name": "text_color", + "value": "#182431" + } + ] +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json new file mode 100644 index 0000000..2375b2d --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + }, + { + "name": "title", + "value": "录音机" + }, + { + "name": "search_recording_files", + "value": "搜索录音文件" + }, + { + "name": "mark", + "value": "标记" + }, + { + "name": "pause", + "value": "暂停" + }, + { + "name": "continue_record", + "value": "继续" + }, + { + "name": "predict_hint", + "value": "预计还能录制10小时以上" + }, + { + "name": "delete_hint", + "value": "是否删除此条录音?" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "delete", + "value": "删除" + }, + { + "name": "has_call_hint", + "value": "通话状态无法录音" + }, + { + "name": "recording_hint", + "value": "录音机正在录音" + }, + { + "name": "suspend_record_hint", + "value": "录音机暂停录音" + } + ] +} diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png new file mode 100644 index 0000000000000000000000000000000000000000..41c12ccb5bb90cd9c05508690ca0b88f33e96008 GIT binary patch literal 3806 zcmdUx2~bnl8pm&BS5adC7Z5~>5L6UdB&-z>DkwaWML?iHA+kjRN!X!QL|N6MD42i* zNkBA$VGZKKs>CG5Kp=!Q2m}Zqpe(Yaw4Kf?4?EMD&YOAf+&Oda{hxFHzwbNe%$-lz zA?yRTSzDg81VA7F0IgntkPDcvzWuZItI0oeSp8b~5&%mAG!R?_v=7(-28n<{!UjNL zHAs=)yn#O&NJ3IfN>qH~>ZsMW)g(ZoBAXyZ@uqj(tb9cd2}%YL;=kX=>GI_v(WDiur@FdIyO~h>DA> zj+uj3V~`L7ZIY4%iTys|SBMx`SzJQv_!+P5vPX5Cypiae*en8CO-cj|m;x(r0hB`DpGdzydeLHr7k|tdD79%Ir8U)OFEHjn z#?9V$lHBFfY$ON36BN%Huf&2#lO&3rFDc%@Eo1|q`t3TKuLwtmo`)^Jv_p0j@SH6N z)^Z9Gkk{ti4|kW;+ds>-=vI5$Zi+ip1w#4W|BBH%X=j)xY^6`FN?<>AARk$>hGSo+ z-w;i@GtuEy6u*s<> z3p&#JM2&guq@bKJY=Z#YcU}03(>h6fcYCK_e4#kV`MI+U>rzDVDUQXNPY1Hga83SY z5B-wLk_EivBD{JTAt}Y}^mK|fzNOf><*zpcDg;haPTz4IN(EEhLbAuwp^u7w+V;1j zQD~>fS4mA6$~?2?cLl9YyR{@;OL44Vv0`U{a|Zw3gIU+%nSx3{Gqr48R-1eMuSNC4 zXgFTB4-MBeXu4-KW|@)5+NS&E(cEL@a3bRECv*!Yz9V-ym%bdo!^dcj;={p)TSvT@ zg$kCrKPPh>Rn?7PLHY=R98Ia(BHv&*)6eWFJ1J_v#>$gr`3lFQi{w`^fq2N2shIzh z2pnuO%4yi{;bYm*$!Ql(oAy|YT=rB-hIZ{pxBMwo8(vcz%*Ow&xCSV_9R= z(g)s>T|SXyf+$ctNJ+}xd*sATTLl;`o(rAGf}2X!XThVteXdnVIg-=AFzyn93P@o4 zlN@qVac^ne|u25+A1zJ4u=O8po*_yqlk%Z_Xbbp4-P5 zUE%a`5ip~yHjCaYcPnEg$zK0(gu^}#e}@{KD~UDN~t7S7SeUC=?t z1gjRFIAh#^+5f0YC%+EjLiC0jz3umZR8vF@&e=P9TWhx5yI+g@GK0$+T3yw83cCn5 zwjF&mC-t*azjmJ^oZP|ca!;M<8M*Fci6nI zjOA7~Y&<4gzA?AliO65L#$h&cW|m@4qZ>P}pRjW`h3UV5@JGh3-z&251)bd_8(zE* zYbXof(HsVyz=q{EJ7B3U-?hwlazm0-AziMoM_*JVW$?DA`a_jva{NsD)3{miWlnt; zB?1>ho$l0!V|v+a#g#2pao8Zm|J=Ff&tqOzOJf$|u8?8WR@EFLP0s8vbyMV0lPT>p zBbB0&p%l_I&UlP9S&~OC>!t7NuKrBE%0W#TS`99QnO^>W3Zue2+ipj2lcAZlPJ z*JSVc#G1&!p+i}8`=!KpDatzsuRMD|oUb#r-J(AIW}XDq5(1kMT~yNvy5bN=nBW#~%7*UeLr8QKJ&yG;En(eXf%qa9GzJ zQDN}P$As4%gV$`2sHNTN;nh)F2u&I(yPjP{O|pDs4oOW@|8e~-MMxD zSPA*dg}73S&nL8db6=SpKNZ?AK9cN{QQBb}i9$EnMfJwI22^;A({(w#D;~3CrewV> zf}Yc0?VyiUvZUQJ8JCaEeWPZ@Vpg`F-qI6&l*8FIJDq1Z`u?`t;jvHLiR0>t^!+A;Y`#FOnC&;eUzJ`!bTpW%#)ns+jaRsKvV47yB;9-HUy#x{Zy( zA7$MmYs{h)5L@t=Mo60sBQ9QaK}?GZsU$$tZJWJdgUoiYF~8R-`|+Kcury3Wo_r_6 zLPZ)@V-O97{)-n9E3X%{SQb1R{|!#b&a&5C$1qYrh5rEOwpa|B_|Fpmg6HvHP6$MAVKP4$llI;+cX@w}YKwSV%z1~5Fi7Ic*g2dvURZ*BkZC?>+jExyGu)Ffe8=j% z#a#Zs4@$ztK;vzxIzxgHfklD2^jN{IbBOV-WjHu9LN}#t+9E!CF3*1^NC@Orb;NrH zW_5r5(J9&_Oq@DKgifu!II_h5K>cF_2~_YWUc9@r8%Y}zF{w!r12*j3$`+=&g*>5YfC zQ;zM<1UIR4qh4U@rLCu9A*dYc`4v<}pBOXq$Mrtzm9=&8TF(DO{VnzmC}{k9eVX;> zy8Kyn(<42$yYjM2$k|iwQ`+ZrViRw^i;{3d80ghCv5WUe-!C`ok0@bfUk@ee;BX3? zNNs$aYA_*iI%;2XdCJKX;cg!qWf|p+V*r9#LwjIug}$42E4D^g&c-s>q-`TipKQiA zOR{$8R>!A>A8?cmxN>%`&0UiFBvEEq`chYh)j6_yhSk{pE5=4zenYdPv7twPQ(mb;I9 literal 0 HcmV?d00001 diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg new file mode 100644 index 0000000..6f7f039 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg @@ -0,0 +1,10 @@ + + + systemicon/back + + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg new file mode 100644 index 0000000..3ec94e4 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg @@ -0,0 +1,8 @@ + + + ic_clock_add + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg new file mode 100644 index 0000000..14a0ba5 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg @@ -0,0 +1,10 @@ + + + ic_clock_enhance + + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg new file mode 100644 index 0000000..330eda7 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg @@ -0,0 +1,8 @@ + + + ic_clock_mark + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg new file mode 100644 index 0000000..4a6c569 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg @@ -0,0 +1,7 @@ + + + ic_clock_play + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg new file mode 100644 index 0000000..c8f7906 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg @@ -0,0 +1,7 @@ + + + ic_clock_record + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg new file mode 100644 index 0000000..0296449 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg @@ -0,0 +1,7 @@ + + + ic_clock_stop + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg new file mode 100644 index 0000000..bf6f0ea --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg @@ -0,0 +1,8 @@ + + + ic_clock_suspend + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg new file mode 100644 index 0000000..34c0e94 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg @@ -0,0 +1,8 @@ + + + ic_record_play + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg new file mode 100644 index 0000000..1b2a8aa --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg @@ -0,0 +1,8 @@ + + + ic_record_search + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg new file mode 100644 index 0000000..2b7ceaa --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg @@ -0,0 +1,9 @@ + + + ic_record_stop + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg new file mode 100644 index 0000000..400c3ef --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg @@ -0,0 +1,13 @@ + + + public_more + + + + + + + + + + \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/package.json b/product/phone/oh_modules/@ohos/recorder/package.json new file mode 100644 index 0000000..83c74cf --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/recorder", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/common": "file:../../common" + } +} diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets new file mode 100644 index 0000000..2b1cae6 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 mediaLibrary from '@ohos.multimedia.mediaLibrary'; +import media from '@ohos.multimedia.media'; +import { LogUtil } from '@ohos/common'; +import { BusinessError, Callback } from '@ohos.base' + +export enum AudioState { + /** + * The initial state + */ + IDLE, + /** + * Continuously update time starting from IDLE state or PAUSED state + */ + RUNNING, + /** + * Click Pause from the RUNNING state + */ + PAUSED, +} + +const NOTIFY_INTERVAL_MS = 50; +const TAG = "AudioController : "; + +export class AudioController { + private audioPlayer?: media.AVPlayer; + private state: string = 'idle'; + private playFile: string = ''; + private dataLoad: boolean = false; + private currentTimeMs: number = 0; + private intervalId: number = -1; + private timeUpdateListener?: Callback; + private stateUpdateListener?: Callback; + + /** + * Set the time update listener + * + * @param listener + */ + public setTimeUpdateListener(tag: string, timeUpdateListener: Callback): void { + LogUtil.info(`${TAG} setTimeUpdateListener`); + this.timeUpdateListener = timeUpdateListener; + } + + /** + * Set the status update listener + * + * @param listener + */ + public setStateUpdateListener(tag: string, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; + } + + /** + * Notification time update + */ + private notifyTimeChanges() { + if (this.timeUpdateListener) { + this.timeUpdateListener(this.currentTimeMs); + } + } + + /** + * Notification of status updates + */ + private async notifyStateChanges() { + if (this.stateUpdateListener) { + LogUtil.info(`${TAG} state update ${this.state}`); + this.stateUpdateListener(this.state); + } + } + + /** + * Initialize the audio player + * + * @param playSrc + * @param callback + */ + async initAudioPlayer(playSrc: string, callback: () => void) { + LogUtil.info(`${TAG} initAudioPlayer`); + this.playFile = playSrc; + this.dataLoad = false; + this.release(); + LogUtil.info(`${TAG} createAudioPlayer`); + if (!this.audioPlayer) { + return; + } + try { + this.audioPlayer = await media.createAVPlayer(); + } catch (e) { + } + this.audioPlayer?.on('stateChange', this.stateChangeListener) + } + + private stateChangeListener = async (state: string, reason: media.StateChangeReason) => { + if (!this.audioPlayer) { + return; + } + this.state = state; + switch (state) { + case 'idle' : + break; + case 'initialized': + break; + case 'playing': + break; + case 'prepared': + break; + case 'paused': + break; + case 'completed': + break; + case 'stopped': + case 'released': + break; + } + } + /** + * audioPlayer play + */ + play() { + try { + if (this.audioPlayer) { + this.audioPlayer.play(); + } + } catch (e) { + } + } + + /** + * audioPlayer seek time + * + * @param timeMs + */ + seek(timeMs: number) { + if (this.audioPlayer) { + LogUtil.info(`${TAG} audioPlayer time to jump. time:` + timeMs); + this.audioPlayer.seek(timeMs); + } + } + + /** + * audioPlayer pause + */ + pause() { + if (this.audioPlayer) { + LogUtil.info(`${TAG} audioPlayer pause`); + this.audioPlayer.pause(); + } + } + + /** + * audioPlayer stop + */ + stop() { + if ((this.audioPlayer) && this.state != 'idle') { + LogUtil.info(`${TAG} audioPlayer stop`); + this.state = 'idle'; + this.audioPlayer.release(); + this.intervalId = -1; + } + } + + /** + * audioPlayer continue play + */ + continuePlay() { + if (this.audioPlayer) { + LogUtil.info(`${TAG} audioPlayer continue play`); + this.audioPlayer.play(); + } + } + + /** + * audioPlayer release + */ + release() { + if (this.audioPlayer) { + this.currentTimeMs = 0; + this.notifyTimeChanges(); + LogUtil.info(`${TAG} audioPlayer release`); + this.audioPlayer.release(); + this.audioPlayer = undefined; + } + } + +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets new file mode 100644 index 0000000..db8262d --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 mediaLibrary from '@ohos.multimedia.mediaLibrary'; +import { Util } from '@ohos/common'; +import { RecordData } from '../model/RecordData'; +import data_preferences from '@ohos.data.preferences'; +import { LogUtil } from '@ohos/common'; + +const TAG = 'MediaController : '; + +export class MediaController { + private mMediaLibrary: mediaLibrary.MediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext); + private preferences?: data_preferences.Preferences; + + constructor() { + this.initPreferences(); + } + + /** + * init Preferences + */ + async initPreferences() { + LogUtil.info(`${TAG} initPreferences.`); + this.preferences = await data_preferences.getPreferences(globalThis.abilityContext, 'myRecorderStore'); + } + + /** + * save File Duration to preferences + * + * @param name + * @param value + */ + async saveFileDuration(name: string, value: number) { + LogUtil.info(`${TAG} saveFileDuration. fileName : ${name}. duration:${value}`); + if (this.preferences) { + await this.preferences.put(name, value); + this.preferences.flush(); + LogUtil.info(`${TAG} save File Duration end.`); + } + } +} + +export default new MediaController(); \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets new file mode 100644 index 0000000..ec15a77 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 media from '@ohos.multimedia.media'; +import { LogUtil } from '@ohos/common'; +import Notification from '@ohos.notification'; +import { BusinessError, Callback } from '@ohos.base' + +const NOTIFY_INTERVAL_MS = 60; +const NOTIFY_ID = 10023; +const TAG = 'RecordController : '; + +export enum RecordState { + IDLE, + RUNNING, + PAUSED, +} + +export class RecordController { + private beforePauseTime: number = 0; + private startTimestamp: number = 0; + private notifierId: number = -1; + private state: string = ''; + private config?: media.AVRecorderConfig; + private openedFileFd?: number; + private currentFilePath?: string; + private recorderDuration: number = 0; + private currentTimeMs: number = 0; + private audioRecorder?: media.AVRecorder; + private timeUpdateListener?: Callback; + private stateUpdateListener?: Callback; + + /** + * Notification time update + */ + private notifyTimeChanges() { + if (this.timeUpdateListener) { + this.timeUpdateListener(this.currentTimeMs); + } + } + + /** + * Notification of status updates + */ + private async notifyStateChanges() { + if (this.stateUpdateListener) { + LogUtil.info(`${TAG} state update. ${this.state}`); + this.stateUpdateListener(this.state); + } + } + + /** + * Set the time update listener + * + * @param listener + */ + public setTimeUpdateListener(tag: string, timeUpdateListener: Callback): void { + LogUtil.info(`${TAG} setTimeUpdateListener`); + this.timeUpdateListener = timeUpdateListener; + } + + /** + * Set the status update listener + * + * @param listener + */ + public setStateUpdateListener(tag: string, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; + } + + /** + * init AudioRecorder + */ + async initAudioRecorder() { + LogUtil.info(`${TAG} initAudioRecorder.`); + if (!this.audioRecorder) { + this.audioRecorder = await media.createAVRecorder(); + } + this.setAVRecorderCallback(this.audioRecorder); + } + + private setAVRecorderCallback(avRecorder: media.AVRecorder): void { + if (!avRecorder) { + return; + } + avRecorder.on('error', async (err: BusinessError) => { + + }); + avRecorder.on('stateChange', async (state: string, resaon: media.StateChangeReason) => { + this.state = state; + switch (state) { + case 'idle': + break; + case 'initialized': + break; + case 'started': + break; + case 'prepared': + break; + case 'paused': + break; + case 'completed': + break; + case 'stopped': + break; + case 'released': + break; + case 'released': + break; + default: + break + } + }); + } + + /** + * Gets the sound size of the recording + */ + getSoundVolume() { //todo + return Math.random() * 100 + 5; + } + + /** + * Recorder start + * + * @param pathName + */ + startRecorder(tag: string, filefd: number, filePath: string, config: media.AVRecorderConfig, + recorderStateCallback: Callback, onErrorCallback?: Callback) { + if (this.audioRecorder) { + this.recorderDuration = 0; + this.currentFilePath = filePath; + this.config = config; + this.openedFileFd = filefd; + if (this.audioRecorder.state === 'idle') { + this.audioRecorder.prepare(config); + } else { + this.audioRecorder.reset(); + } + LogUtil.info(`${TAG} audioRecorder prepare.`); + ; + } else { + LogUtil.error(`${TAG} case failed, audioRecorder is null.`); + } + } + + /** + * Recorder pause + */ + pause() { + if (this.audioRecorder) { + LogUtil.info(`${TAG} audioRecorder pause`); + this.audioRecorder.pause(); + } + } + + /** + * Recorder resume + */ + resume() { + if (this.audioRecorder) { + LogUtil.info(`${TAG} audioRecorder resume`); + this.audioRecorder.resume(); + } + } + + /** + * Recorder stop + */ + stop() { + if (this.audioRecorder) { + LogUtil.info(`${TAG} audioRecorder stop`); + this.audioRecorder.stop(); + } + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets new file mode 100644 index 0000000..bf5bc9a --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { LogUtil } from '@ohos/common'; +import { BusinessError, Callback } from '@ohos.base' + +const TAG = 'ControlState : '; + +export enum ControlState { + START, + END, +} + +export class StateController { + private state: number = 1; + private stateUpdateListener?: Callback; + + /** + * Set the status update listener + * + * @param listener + */ + public setStateUpdateListener(tag: number, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; + } + + /** + * Notification of status updates + */ + private async notifyStateChanges() { + if (this.stateUpdateListener) { + this.stateUpdateListener(this.state); + } + } + + /** + * Announce the start of recording + */ + public start() { + LogUtil.info(`${TAG} record start.`); + this.state = ControlState.START; + this.notifyStateChanges(); + } + + /** + * Announce the end of recording + */ + public end() { + LogUtil.info(`${TAG} record end.`); + this.state = ControlState.END; + this.notifyStateChanges(); + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets b/product/phone/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets new file mode 100644 index 0000000..ab6a485 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { MediaController } from '../controller/MediaController'; +import mediaLibrary from '@ohos.multimedia.mediaLibrary'; + +export class RecordData { + fileAsset: string = ''; + title: string = ''; + duration: number = 0; + date: number = 0; + + constructor(fileAsset: number, date: number, title: string) { + if (fileAsset) { + if (fileAsset > 0) { + this.duration = fileAsset; + } else { + this.duration = 0; + } + if (date > 0) { + this.date = date; + } else { + this.date = 0; + } + this.title = title; + } else { + this.duration = 0; + this.title = ''; + } + } +} \ No newline at end of file diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/module.json5 b/product/phone/oh_modules/@ohos/recorder/src/main/module.json5 new file mode 100644 index 0000000..ed1e039 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "recorder", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/product/phone/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json b/product/phone/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/product/phone/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/product/phone/src/main/ets/Application/MyAbilityStage.ts b/product/phone/src/main/ets/Application/MyAbilityStage.ts index 0a9efc1..06ad1b3 100644 --- a/product/phone/src/main/ets/Application/MyAbilityStage.ts +++ b/product/phone/src/main/ets/Application/MyAbilityStage.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import AbilityStage from "@ohos.application.AbilityStage" +import AbilityStage from "@ohos.app.ability.AbilityStage" export default class MyAbilityStage extends AbilityStage { onCreate() { diff --git a/product/phone/src/main/ets/MainAbility/MainAbility.ts b/product/phone/src/main/ets/MainAbility/MainAbility.ts index a92c2d5..a0be8b4 100644 --- a/product/phone/src/main/ets/MainAbility/MainAbility.ts +++ b/product/phone/src/main/ets/MainAbility/MainAbility.ts @@ -13,50 +13,37 @@ * limitations under the License. */ -import Ability from '@ohos.application.Ability' +import Ability from '@ohos.app.ability.Ability' import Notification from '@ohos.notification'; -import { LogUtils } from '@ohos/common/src/main/ets/utils/LogUtils' export default class MainAbility extends Ability { onCreate(want, launchParam) { - LogUtils.log("[Demo] MainAbility onCreate") + console.log("[Demo] MainAbility onCreate") globalThis.abilityWant = want; - globalThis.abilityContext = this.context; } onDestroy() { Notification.cancelAll() - LogUtils.log("[Demo] MainAbility onDestroy") + console.log("[Demo] MainAbility onDestroy") } onWindowStageCreate(windowStage) { // Main window is created, set main page for this ability - LogUtils.log("[Demo] MainAbility onWindowStageCreate") - this.context.requestPermissionsFromUser(['ohos.permission.MICROPHONE', 'ohos.permission.WRITE_MEDIA', 'ohos.permission.READ_MEDIA']).then(() => { - Notification.requestEnableNotification().then(() => { - windowStage.loadContent("pages/index", (err, data) => { - if (err.code) { - LogUtils.error('Failed to load the content. Cause:' + JSON.stringify(err)); - return; - } - LogUtils.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) - }); - }) - }) + console.log("[Demo] MainAbility onWindowStageCreate") } onWindowStageDestroy() { // Main window is destroyed, release UI related resources - LogUtils.log("[Demo] MainAbility onWindowStageDestroy") + console.log("[Demo] MainAbility onWindowStageDestroy") } onForeground() { // Ability has brought to foreground - LogUtils.log("[Demo] MainAbility onForeground") + console.log("[Demo] MainAbility onForeground") } onBackground() { // Ability has back to background - LogUtils.log("[Demo] MainAbility onBackground") + console.log("[Demo] MainAbility onBackground") } }; diff --git a/product/phone/src/main/ets/pages/RecordingPage.ets b/product/phone/src/main/ets/pages/RecordingPage.ets index a99deb4..ebe5bf0 100644 --- a/product/phone/src/main/ets/pages/RecordingPage.ets +++ b/product/phone/src/main/ets/pages/RecordingPage.ets @@ -14,7 +14,7 @@ */ import { ConfigData, Util } from '@ohos/common' -import { RecordController, MediaController, RecordState } from '@ohos/recorder' +import { RecordController, MediaController, RecordState, RecordData } from '@ohos/recorder' import router from '@ohos.router'; import mediaLibrary from '@ohos.multimedia.mediaLibrary' import prompt from '@ohos.prompt'; @@ -30,27 +30,10 @@ struct RecordingPage { @State currentTime: number = 0 @State state: RecordState = RecordState.IDLE private recordController: RecordController = new RecordController() - @State fileAsset: mediaLibrary.FileAsset = undefined heightList: Array = [] mIntervalId = -1 async aboutToAppear() { - let that = this - this.recordController.setTimeUpdateListener((currentTimeMs: number) => { - if (Math.floor(currentTimeMs / (TIME_COUNT / 2 * 1000 * TIME_INTERVAL_S / VOICE_FREQUENCY)) - Math.floor(this.currentTime / (TIME_COUNT / 2 * 1000 * TIME_INTERVAL_S / VOICE_FREQUENCY)) == 1) { - that.heightList.splice(0, 1) - that.heightList.push(this.recordController.getSoundVolume()) - } - this.currentTime = currentTimeMs - }) - this.recordController.setStateUpdateListener((state) => { - this.state = state - }) - this.recordController.initAudioRecorder() - this.fileAsset = await MediaController.createAudioFile() - let fd = await this.fileAsset.open('Rw') - this.recordController.startRecorder(`fd://${fd}`) - this.initHeightList() } aboutToDisappear() { @@ -95,7 +78,7 @@ struct RecordingPage { Stack({ alignContent: Alignment.Top }) { Column() { Row() { - ForEach(Array.from(Array(TIME_COUNT + 1).keys()), (item) => { + ForEach(Array.from(Array(TIME_COUNT + 1).keys()), (item:number) => { Column() { Text(Util.timeFormat(((item - (TIME_COUNT - 1) / 2) * 1000 * TIME_INTERVAL_S + Math.floor(this.currentTime / (1000 * TIME_INTERVAL_S)) * (1000 * TIME_INTERVAL_S)), false)) .textAlign(TextAlign.Center) @@ -103,19 +86,19 @@ struct RecordingPage { .fontSize($r("app.float.font_20")) .opacity($r("app.float.opacity_6")) Row() { - ForEach(Array.from(Array(5).keys()), (scaleItem) => { + ForEach(Array.from(Array(5).keys()), (scaleItem:number) => { Rect() .width($r("app.float.wh_value_2_5")) .fill($r("app.color.text_color")) .height(scaleItem == 2 ? $r("app.float.wh_value_26_5") : $r("app.float.wh_value_13_5")) .opacity(scaleItem == 2 ? $r("app.float.opacity_4") : $r("app.float.opacity_2")) - }, scaleItem => scaleItem) + }, (scaleItem:number) => scaleItem+'') }.width(ConfigData.WH_100_100) .alignItems(VerticalAlign.Top) .height($r("app.float.wh_value_26_5")) .justifyContent(FlexAlign.SpaceAround) }.width((100 / TIME_COUNT) + "%") - }, item => item) + }, (item:number) => item+'') } .offset({ x: (-(100 / TIME_COUNT) * (this.currentTime % (TIME_INTERVAL_S * 1000) / (TIME_INTERVAL_S * 1000))) + "%" @@ -124,13 +107,13 @@ struct RecordingPage { Row() { Row() { Row() { - ForEach(Array.from(Array(VOICE_FREQUENCY).keys()), (item) => { + ForEach(Array.from(Array(VOICE_FREQUENCY).keys()), (item:number) => { Rect() .width($r("app.float.wh_value_2_5")) .fill($r("app.color.text_color")) .height(this.heightList[item]) .opacity($r("app.float.opacity_2")) - }, item => item) + }, (item: number) => item+'') }.width(ConfigData.WH_100_100) .justifyContent(FlexAlign.SpaceAround) .offset({ @@ -201,21 +184,11 @@ struct RecordingPage { if (this.state == RecordState.IDLE) { let hasCall = await call.hasCall() if (hasCall) { - prompt.showToast({ message: $r('app.string.has_call_hint') }) } else { this.recordController.initAudioRecorder() - this.fileAsset = await MediaController.createAudioFile() - let fd = await this.fileAsset.open('Rw') - this.recordController.startRecorder(`fd://${fd}`) } } else { - this.recordController.stop(() => { - this.initHeightList() - MediaController.saveFileDuration(this.fileAsset.title, this.currentTime) - router.replace({ - url: "pages/index" - }) - }) + this.recordController.stop(); } }) diff --git a/product/phone/src/main/ets/pages/index.ets b/product/phone/src/main/ets/pages/index.ets index fa199ba..8039e61 100644 --- a/product/phone/src/main/ets/pages/index.ets +++ b/product/phone/src/main/ets/pages/index.ets @@ -28,38 +28,12 @@ struct Index { private audioController: AudioController = new AudioController() @State state: AudioState = AudioState.IDLE; @State filterText: string = ""; - private deleteRecord: RecordData = undefined - confirm: () => void = () => { - MediaController.deleteRecord(this.deleteRecord.fileAsset.uri, () => { - for (let i = this.recordList.length - 1;i >= 0; i--) { - if (this.deleteRecord.fileAsset.uri == this.recordList[i].fileAsset.uri) { - this.recordList.splice(i, 1) - } - } - }) - } - dialogController: CustomDialogController = new CustomDialogController({ - builder: DeleteRecordDialog({ deleteRecordTitle: this.deleteRecord.title, confirm: this.confirm }), - autoCancel: true, - alignment: DialogAlignment.Bottom, - offset: { dy: -64, dx: 0 } - }) + private deleteRecord?: RecordData; async getAudios() { - this.recordList = await MediaController.queryAllAudios() } aboutToAppear() { - this.getAudios() - this.audioController.setTimeUpdateListener((currentTime: number) => { - this.currentTime = currentTime - }) - this.audioController.setStateUpdateListener((state: AudioState) => { - if (state == AudioState.IDLE) { - this.selectedIndex = -1 - } - this.state = state - }) } build() { @@ -109,19 +83,17 @@ struct Index { Column() { List() { - ForEach([...this.recordList].reverse().map((value, index) => { - return { i: index, data: value } - }), (item) => { + ForEach([...this.recordList].reverse(), (item: RecordData, index:number) => { ListItem() { Column() { Row() { Column() { - Text(item.data.title) + Text(item.title) .fontColor($r("app.color.text_color")) .fontSize($r("app.float.font_32")) .width($r("app.float.wh_value_280")) .lineHeight($r("app.float.wh_value_28")) - Text(Util.getDateFormat(item.data.date)) + Text(Util.getDateFormat(item.date)) .fontColor($r("app.color.text_color")) .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_28")) @@ -130,12 +102,12 @@ struct Index { } Row() { - Text(Util.timeFormat(item.data.duration)) + Text(Util.timeFormat(item.duration)) .fontColor($r("app.color.text_color")) .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_28")) .margin({ right: $r("app.float.distance_2_5") }) - Image((item.i == this.selectedIndex && this.state == AudioState.RUNNING) ? $r("app.media.ic_record_stop") : $r("app.media.ic_record_play")) + Image((index == this.selectedIndex && this.state == AudioState.RUNNING) ? $r("app.media.ic_record_stop") : $r("app.media.ic_record_play")) .width($r("app.float.wh_value_32")) .height($r("app.float.wh_value_32")) } @@ -145,9 +117,9 @@ struct Index { .justifyContent(FlexAlign.SpaceBetween) .padding({ left: $r("app.float.distance_21_5"), right: $r("app.float.distance_21_5") }) .onClick(() => { - if (this.selectedIndex != item.i || this.state == AudioState.IDLE) { - this.selectedIndex = item.i - this.audioController.initAudioPlayer(item.data.fileAsset, () => { + if (this.selectedIndex != index || this.state == AudioState.IDLE) { + this.selectedIndex = index + this.audioController.initAudioPlayer(item.fileAsset, () => { this.audioController.play() }) } else if (this.state == AudioState.RUNNING) { @@ -160,17 +132,15 @@ struct Index { LongPressGesture() .onAction(() => { this.audioController.stop() - this.deleteRecord = item.data - this.dialogController.open() }) ) - if (this.selectedIndex == item.i) { + if (this.selectedIndex == index) { Column() { Slider({ value: this.currentTime, min: 0, - max: item.data.duration, + max: item.duration, style: SliderStyle.OutSet }) .width($r("app.float.wh_value_433")) @@ -187,7 +157,7 @@ struct Index { .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_20")) .margin({ right: $r("app.float.distance_2_5") }) - Text(Util.timeFormat(item.data.duration)) + Text(Util.timeFormat(item.duration)) .fontColor($r("app.color.text_color")) .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_20")) @@ -200,8 +170,8 @@ struct Index { .width(ConfigData.WH_100_100) } } - }.visibility(item.data.title.indexOf(this.filterText) >= 0 ? Visibility.Visible : Visibility.None) - }, item => item.i) + }.visibility(item.title.indexOf(this.filterText) >= 0 ? Visibility.Visible : Visibility.None) + }, (index:number) => index+'') }.width(ConfigData.WH_100_100) .backgroundColor($r("app.color.white")) @@ -232,7 +202,6 @@ struct Index { this.audioController.stop() let hasCall = await call.hasCall() if (hasCall) { - prompt.showToast({ message: $r('app.string.has_call_hint') }) } else { router.replace({ url: "pages/RecordingPage" @@ -259,8 +228,8 @@ struct Index { @CustomDialog struct DeleteRecordDialog { private controller: CustomDialogController - private deleteRecordTitle: string - private confirm: () => void + private deleteRecordTitle: string = ''; + private confirm: () =>void = ()=>{}; build() { Column() { diff --git a/product/phone/src/main/module.json5 b/product/phone/src/main/module.json5 index 4bd4b49..2ca2871 100644 --- a/product/phone/src/main/module.json5 +++ b/product/phone/src/main/module.json5 @@ -2,7 +2,7 @@ "module": { "name": "phone", "type": "entry", - "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "srcEntry": "./ets/Application/MyAbilityStage.ts", "description": "$string:phone_desc", "mainElement": "MainAbility", "deviceTypes": [ @@ -15,7 +15,7 @@ "abilities": [ { "name": "MainAbility", - "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "srcEntry": "./ets/MainAbility/MainAbility.ts", "description": "$string:MainAbility_desc", "icon": "$media:icon", "label": "$string:MainAbility_label", @@ -31,19 +31,25 @@ "action.system.home" ] } - ] + ], } ], "requestPermissions": [ - { - "name": "ohos.permission.MICROPHONE" - }, - { - "name": "ohos.permission.WRITE_MEDIA" - }, - { - "name": "ohos.permission.READ_MEDIA" - } + //{ + //"name": "ohos.permission.MICROPHONE", + //"reason": This is used to record audio., + //"usedScene": { + // "abilities":[ + // "MainAbility" + // ] + //} + //}, + //{ + // "name": "ohos.permission.WRITE_MEDIA" + //}, + //{ + // "name": "ohos.permission.READ_MEDIA" + //} ] } } \ No newline at end of file diff --git a/product/tablet/oh-package-lock.json5 b/product/tablet/oh-package-lock.json5 new file mode 100644 index 0000000..545f332 --- /dev/null +++ b/product/tablet/oh-package-lock.json5 @@ -0,0 +1,25 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/common@../../common": "@ohos/common@../../common", + "@ohos/recorder@../../feature/recorder": "@ohos/recorder@../../feature/recorder" + }, + "packages": { + "@ohos/common@../../common": { + "name": "@ohos/common", + "version": "1.0.0", + "resolved": "../../common", + "registryType": "local" + }, + "@ohos/recorder@../../feature/recorder": { + "name": "@ohos/recorder", + "version": "1.0.0", + "resolved": "../../feature/recorder", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/product/tablet/oh-package.json5 b/product/tablet/oh-package.json5 new file mode 100644 index 0000000..2ba09c9 --- /dev/null +++ b/product/tablet/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "devDependencies": {}, + "name": "tablet", + "description": "example description", + "version": "1.0.0", + "dynamicDependencies": {}, + "dependencies": { + "@ohos/recorder": "file:../../feature/recorder", + "@ohos/common": "file:../../common" + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/.gitignore b/product/tablet/oh_modules/@ohos/common/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/BuildProfile.ets b/product/tablet/oh_modules/@ohos/common/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/build-profile.json5 b/product/tablet/oh_modules/@ohos/common/build-profile.json5 new file mode 100644 index 0000000..7374b5c --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/build-profile.json5 @@ -0,0 +1,17 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + } + } + } + }, + ] +} diff --git a/product/tablet/oh_modules/@ohos/common/hvigorfile.js b/product/tablet/oh_modules/@ohos/common/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/product/tablet/oh_modules/@ohos/common/index.ets b/product/tablet/oh_modules/@ohos/common/index.ets new file mode 100644 index 0000000..af9c605 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/index.ets @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { default as ConfigData } from './src/main/ets/utils/ConfigData' + +export { default as Util } from './src/main/ets/utils/Util' + +export { default as LogUtil } from './src/main/ets/utils/LogUtil' diff --git a/product/tablet/oh_modules/@ohos/common/oh-package.json5 b/product/tablet/oh_modules/@ohos/common/oh-package.json5 new file mode 100644 index 0000000..3159c13 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "index.ets", + "version": "1.0.0", +} diff --git a/product/tablet/oh_modules/@ohos/common/package.json b/product/tablet/oh_modules/@ohos/common/package.json new file mode 100644 index 0000000..dfbf6f7 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/hap": "^3.0.0" + } +} diff --git a/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets b/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets new file mode 100644 index 0000000..728136a --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 class ConfigData { + WH_100_100 = '100%'; + WH_50_100 = '50%'; + WH_40_100 = '40%'; + WH_20_100 = '20%'; +} + +let configData = new ConfigData(); + +export default configData as ConfigData; \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts b/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts new file mode 100644 index 0000000..bbead9d --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 HiLog from "@ohos.hilog"; + +const DOMAIN = 0x0500; +const TAG = "[Recorder]"; + +/** + * log package tool class + */ +export default class LogUtil { + static debug(msg): void { + HiLog.debug(DOMAIN, TAG, msg); + } + + static log(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static info(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static warn(msg): void { + HiLog.warn(DOMAIN, TAG, msg); + } + + static error(msg): void { + HiLog.error(DOMAIN, TAG, msg); + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/Util.ets b/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/Util.ets new file mode 100644 index 0000000..d7ff070 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/ets/utils/Util.ets @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 default class Util { + + /** + * Time format is converted to seconds + * + * @param timestamp + * @param hasHour + */ + static timeFormat(timestamp: number, hasHour: boolean = true): string { + if (timestamp < 0) { + return ""; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hasHour || hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + return timeStr; + } + + /** + * Time format is converted to milliseconds + * + * @param timestamp + */ + static timeFormatMs(timestamp: number): string { + if (timestamp <= 0) { + return "00:00.00"; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + if (hour < 1) { + let mSec = Math.floor(timestamp % 1000 / 10); + timeStr += "." + Util.addZero(mSec); + } + return timeStr; + } + + /** + * Gets the date at the specified time + * + * @param date + */ + static getDateFormat(date: number): string { + let nowDate = new Date(date); + return nowDate.getFullYear() + "/" + Util.addZero(nowDate.getMonth() + 1) + "/" + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the specified time + * + * @param date + */ + static getTimeFormat(date: number): string { + let nowDate = new Date(date); + return Util.addZero(nowDate.getHours()) + ":" + Util.addZero(nowDate.getMinutes()) + ":" + Util.addZero(nowDate.getSeconds()); + } + + /** + * Gets the current time date + */ + static getDate(): string { + let nowDate = new Date(); + return nowDate.getFullYear() + Util.addZero(nowDate.getMonth() + 1) + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the current time + */ + static getTime(): string { + let nowDate = new Date(); + return Util.addZero(nowDate.getHours()) + Util.addZero(nowDate.getMinutes()) + Util.addZero(nowDate.getSeconds()); + } + + /** + * If the number is less than 10, add "0". + * + * @param num + */ + static addZero(num: number): string{ + return (num < 10 ? "0" + num : num).toString(); + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/module.json5 b/product/tablet/oh_modules/@ohos/common/src/main/module.json5 new file mode 100644 index 0000000..56a91a8 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "common", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/color.json b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/color.json new file mode 100644 index 0000000..ffe7272 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/color.json @@ -0,0 +1,32 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "background_color", + "value": "#F1F3F5" + }, + { + "name": "shadow_color", + "value": "#11000000" + }, + { + "name": "pointer_color", + "value": "#007DFF" + }, + { + "name": "warn_color", + "value": "#FF595A" + }, + { + "name": "hint_color", + "value": "#007DFF" + }, + { + "name": "text_color", + "value": "#182431" + } + ] +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/string.json b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/string.json new file mode 100644 index 0000000..2375b2d --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + }, + { + "name": "title", + "value": "录音机" + }, + { + "name": "search_recording_files", + "value": "搜索录音文件" + }, + { + "name": "mark", + "value": "标记" + }, + { + "name": "pause", + "value": "暂停" + }, + { + "name": "continue_record", + "value": "继续" + }, + { + "name": "predict_hint", + "value": "预计还能录制10小时以上" + }, + { + "name": "delete_hint", + "value": "是否删除此条录音?" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "delete", + "value": "删除" + }, + { + "name": "has_call_hint", + "value": "通话状态无法录音" + }, + { + "name": "recording_hint", + "value": "录音机正在录音" + }, + { + "name": "suspend_record_hint", + "value": "录音机暂停录音" + } + ] +} diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png new file mode 100644 index 0000000000000000000000000000000000000000..41c12ccb5bb90cd9c05508690ca0b88f33e96008 GIT binary patch literal 3806 zcmdUx2~bnl8pm&BS5adC7Z5~>5L6UdB&-z>DkwaWML?iHA+kjRN!X!QL|N6MD42i* zNkBA$VGZKKs>CG5Kp=!Q2m}Zqpe(Yaw4Kf?4?EMD&YOAf+&Oda{hxFHzwbNe%$-lz zA?yRTSzDg81VA7F0IgntkPDcvzWuZItI0oeSp8b~5&%mAG!R?_v=7(-28n<{!UjNL zHAs=)yn#O&NJ3IfN>qH~>ZsMW)g(ZoBAXyZ@uqj(tb9cd2}%YL;=kX=>GI_v(WDiur@FdIyO~h>DA> zj+uj3V~`L7ZIY4%iTys|SBMx`SzJQv_!+P5vPX5Cypiae*en8CO-cj|m;x(r0hB`DpGdzydeLHr7k|tdD79%Ir8U)OFEHjn z#?9V$lHBFfY$ON36BN%Huf&2#lO&3rFDc%@Eo1|q`t3TKuLwtmo`)^Jv_p0j@SH6N z)^Z9Gkk{ti4|kW;+ds>-=vI5$Zi+ip1w#4W|BBH%X=j)xY^6`FN?<>AARk$>hGSo+ z-w;i@GtuEy6u*s<> z3p&#JM2&guq@bKJY=Z#YcU}03(>h6fcYCK_e4#kV`MI+U>rzDVDUQXNPY1Hga83SY z5B-wLk_EivBD{JTAt}Y}^mK|fzNOf><*zpcDg;haPTz4IN(EEhLbAuwp^u7w+V;1j zQD~>fS4mA6$~?2?cLl9YyR{@;OL44Vv0`U{a|Zw3gIU+%nSx3{Gqr48R-1eMuSNC4 zXgFTB4-MBeXu4-KW|@)5+NS&E(cEL@a3bRECv*!Yz9V-ym%bdo!^dcj;={p)TSvT@ zg$kCrKPPh>Rn?7PLHY=R98Ia(BHv&*)6eWFJ1J_v#>$gr`3lFQi{w`^fq2N2shIzh z2pnuO%4yi{;bYm*$!Ql(oAy|YT=rB-hIZ{pxBMwo8(vcz%*Ow&xCSV_9R= z(g)s>T|SXyf+$ctNJ+}xd*sATTLl;`o(rAGf}2X!XThVteXdnVIg-=AFzyn93P@o4 zlN@qVac^ne|u25+A1zJ4u=O8po*_yqlk%Z_Xbbp4-P5 zUE%a`5ip~yHjCaYcPnEg$zK0(gu^}#e}@{KD~UDN~t7S7SeUC=?t z1gjRFIAh#^+5f0YC%+EjLiC0jz3umZR8vF@&e=P9TWhx5yI+g@GK0$+T3yw83cCn5 zwjF&mC-t*azjmJ^oZP|ca!;M<8M*Fci6nI zjOA7~Y&<4gzA?AliO65L#$h&cW|m@4qZ>P}pRjW`h3UV5@JGh3-z&251)bd_8(zE* zYbXof(HsVyz=q{EJ7B3U-?hwlazm0-AziMoM_*JVW$?DA`a_jva{NsD)3{miWlnt; zB?1>ho$l0!V|v+a#g#2pao8Zm|J=Ff&tqOzOJf$|u8?8WR@EFLP0s8vbyMV0lPT>p zBbB0&p%l_I&UlP9S&~OC>!t7NuKrBE%0W#TS`99QnO^>W3Zue2+ipj2lcAZlPJ z*JSVc#G1&!p+i}8`=!KpDatzsuRMD|oUb#r-J(AIW}XDq5(1kMT~yNvy5bN=nBW#~%7*UeLr8QKJ&yG;En(eXf%qa9GzJ zQDN}P$As4%gV$`2sHNTN;nh)F2u&I(yPjP{O|pDs4oOW@|8e~-MMxD zSPA*dg}73S&nL8db6=SpKNZ?AK9cN{QQBb}i9$EnMfJwI22^;A({(w#D;~3CrewV> zf}Yc0?VyiUvZUQJ8JCaEeWPZ@Vpg`F-qI6&l*8FIJDq1Z`u?`t;jvHLiR0>t^!+A;Y`#FOnC&;eUzJ`!bTpW%#)ns+jaRsKvV47yB;9-HUy#x{Zy( zA7$MmYs{h)5L@t=Mo60sBQ9QaK}?GZsU$$tZJWJdgUoiYF~8R-`|+Kcury3Wo_r_6 zLPZ)@V-O97{)-n9E3X%{SQb1R{|!#b&a&5C$1qYrh5rEOwpa|B_|Fpmg6HvHP6$MAVKP4$llI;+cX@w}YKwSV%z1~5Fi7Ic*g2dvURZ*BkZC?>+jExyGu)Ffe8=j% z#a#Zs4@$ztK;vzxIzxgHfklD2^jN{IbBOV-WjHu9LN}#t+9E!CF3*1^NC@Orb;NrH zW_5r5(J9&_Oq@DKgifu!II_h5K>cF_2~_YWUc9@r8%Y}zF{w!r12*j3$`+=&g*>5YfC zQ;zM<1UIR4qh4U@rLCu9A*dYc`4v<}pBOXq$Mrtzm9=&8TF(DO{VnzmC}{k9eVX;> zy8Kyn(<42$yYjM2$k|iwQ`+ZrViRw^i;{3d80ghCv5WUe-!C`ok0@bfUk@ee;BX3? zNNs$aYA_*iI%;2XdCJKX;cg!qWf|p+V*r9#LwjIug}$42E4D^g&c-s>q-`TipKQiA zOR{$8R>!A>A8?cmxN>%`&0UiFBvEEq`chYh)j6_yhSk{pE5=4zenYdPv7twPQ(mb;I9 literal 0 HcmV?d00001 diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg new file mode 100644 index 0000000..6f7f039 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg @@ -0,0 +1,10 @@ + + + systemicon/back + + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg new file mode 100644 index 0000000..3ec94e4 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg @@ -0,0 +1,8 @@ + + + ic_clock_add + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg new file mode 100644 index 0000000..14a0ba5 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg @@ -0,0 +1,10 @@ + + + ic_clock_enhance + + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg new file mode 100644 index 0000000..330eda7 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg @@ -0,0 +1,8 @@ + + + ic_clock_mark + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg new file mode 100644 index 0000000..4a6c569 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg @@ -0,0 +1,7 @@ + + + ic_clock_play + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg new file mode 100644 index 0000000..c8f7906 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg @@ -0,0 +1,7 @@ + + + ic_clock_record + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg new file mode 100644 index 0000000..0296449 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg @@ -0,0 +1,7 @@ + + + ic_clock_stop + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg new file mode 100644 index 0000000..bf6f0ea --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg @@ -0,0 +1,8 @@ + + + ic_clock_suspend + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg new file mode 100644 index 0000000..34c0e94 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg @@ -0,0 +1,8 @@ + + + ic_record_play + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg new file mode 100644 index 0000000..1b2a8aa --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg @@ -0,0 +1,8 @@ + + + ic_record_search + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg new file mode 100644 index 0000000..2b7ceaa --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg @@ -0,0 +1,9 @@ + + + ic_record_stop + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg new file mode 100644 index 0000000..400c3ef --- /dev/null +++ b/product/tablet/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg @@ -0,0 +1,13 @@ + + + public_more + + + + + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/.gitignore b/product/tablet/oh_modules/@ohos/recorder/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/BuildProfile.ets b/product/tablet/oh_modules/@ohos/recorder/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/build-profile.json5 b/product/tablet/oh_modules/@ohos/recorder/build-profile.json5 new file mode 100644 index 0000000..35dff6d --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/build-profile.json5 @@ -0,0 +1,5 @@ +{ + "apiType": "stageMode", + "buildOption": { + } +} diff --git a/product/tablet/oh_modules/@ohos/recorder/hvigorfile.js b/product/tablet/oh_modules/@ohos/recorder/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/product/tablet/oh_modules/@ohos/recorder/index.ets b/product/tablet/oh_modules/@ohos/recorder/index.ets new file mode 100644 index 0000000..98c6430 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/index.ets @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { RecordController, RecordState } from './src/main/ets/controller/RecordController' + +export { default as MediaController } from './src/main/ets/controller/MediaController' + +export { AudioController, AudioState } from './src/main/ets/controller/AudioController' + +export { StateController, ControlState } from './src/main/ets/controller/StateController' + +export { RecordData } from './src/main/ets/model/RecordData' diff --git a/product/tablet/oh_modules/@ohos/recorder/oh-package-lock.json5 b/product/tablet/oh_modules/@ohos/recorder/oh-package-lock.json5 new file mode 100644 index 0000000..71fb2aa --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh-package-lock.json5 @@ -0,0 +1,18 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/common@../../common": "@ohos/common@../../common" + }, + "packages": { + "@ohos/common@../../common": { + "name": "@ohos/common", + "version": "1.0.0", + "resolved": "../../common", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh-package.json5 b/product/tablet/oh_modules/@ohos/recorder/oh-package.json5 new file mode 100644 index 0000000..c395a28 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh-package.json5 @@ -0,0 +1,13 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": { + "@ohos/common": "file:../../common" + }, + "name": "@ohos/recorder", + "description": "a npm package which contains arkUI2.0 page", + "main": "index.ets", + "version": "1.0.0", + "dynamicDependencies": {}, + "dependencies": {} +} diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore new file mode 100644 index 0000000..4f9a973 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets new file mode 100644 index 0000000..3a501e5 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 new file mode 100644 index 0000000..7374b5c --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/build-profile.json5 @@ -0,0 +1,17 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + } + } + } + }, + ] +} diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js new file mode 100644 index 0000000..42ed4b4 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/hvigorfile.js @@ -0,0 +1,3 @@ +// 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').harTasks + diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets new file mode 100644 index 0000000..af9c605 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/index.ets @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { default as ConfigData } from './src/main/ets/utils/ConfigData' + +export { default as Util } from './src/main/ets/utils/Util' + +export { default as LogUtil } from './src/main/ets/utils/LogUtil' diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 new file mode 100644 index 0000000..3159c13 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "index.ets", + "version": "1.0.0", +} diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json new file mode 100644 index 0000000..dfbf6f7 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/common", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/hap": "^3.0.0" + } +} diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets new file mode 100644 index 0000000..728136a --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/ConfigData.ets @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 class ConfigData { + WH_100_100 = '100%'; + WH_50_100 = '50%'; + WH_40_100 = '40%'; + WH_20_100 = '20%'; +} + +let configData = new ConfigData(); + +export default configData as ConfigData; \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts new file mode 100644 index 0000000..bbead9d --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/LogUtil.ts @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 HiLog from "@ohos.hilog"; + +const DOMAIN = 0x0500; +const TAG = "[Recorder]"; + +/** + * log package tool class + */ +export default class LogUtil { + static debug(msg): void { + HiLog.debug(DOMAIN, TAG, msg); + } + + static log(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static info(msg): void { + HiLog.info(DOMAIN, TAG, msg); + } + + static warn(msg): void { + HiLog.warn(DOMAIN, TAG, msg); + } + + static error(msg): void { + HiLog.error(DOMAIN, TAG, msg); + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets new file mode 100644 index 0000000..d7ff070 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/ets/utils/Util.ets @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 default class Util { + + /** + * Time format is converted to seconds + * + * @param timestamp + * @param hasHour + */ + static timeFormat(timestamp: number, hasHour: boolean = true): string { + if (timestamp < 0) { + return ""; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hasHour || hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + return timeStr; + } + + /** + * Time format is converted to milliseconds + * + * @param timestamp + */ + static timeFormatMs(timestamp: number): string { + if (timestamp <= 0) { + return "00:00.00"; + } + let timeStr = ""; + let hour = Math.floor(timestamp % (24 * 60 * 60 * 1000) / (60 * 60 * 1000)); + if (hour > 0) { + timeStr += Util.addZero(hour) + ":"; + } + let min = Math.floor(timestamp % (60 * 60 * 1000) / (60 * 1000)); + timeStr += Util.addZero(min) + ":"; + let sec = Math.floor(timestamp % (60 * 1000) / 1000); + timeStr += Util.addZero(sec); + if (hour < 1) { + let mSec = Math.floor(timestamp % 1000 / 10); + timeStr += "." + Util.addZero(mSec); + } + return timeStr; + } + + /** + * Gets the date at the specified time + * + * @param date + */ + static getDateFormat(date: number): string { + let nowDate = new Date(date); + return nowDate.getFullYear() + "/" + Util.addZero(nowDate.getMonth() + 1) + "/" + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the specified time + * + * @param date + */ + static getTimeFormat(date: number): string { + let nowDate = new Date(date); + return Util.addZero(nowDate.getHours()) + ":" + Util.addZero(nowDate.getMinutes()) + ":" + Util.addZero(nowDate.getSeconds()); + } + + /** + * Gets the current time date + */ + static getDate(): string { + let nowDate = new Date(); + return nowDate.getFullYear() + Util.addZero(nowDate.getMonth() + 1) + Util.addZero(nowDate.getDate()); + } + + /** + * Gets the hour, minute and second of the current time + */ + static getTime(): string { + let nowDate = new Date(); + return Util.addZero(nowDate.getHours()) + Util.addZero(nowDate.getMinutes()) + Util.addZero(nowDate.getSeconds()); + } + + /** + * If the number is less than 10, add "0". + * + * @param num + */ + static addZero(num: number): string{ + return (num < 10 ? "0" + num : num).toString(); + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 new file mode 100644 index 0000000..56a91a8 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "common", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json new file mode 100644 index 0000000..ffe7272 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/color.json @@ -0,0 +1,32 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "background_color", + "value": "#F1F3F5" + }, + { + "name": "shadow_color", + "value": "#11000000" + }, + { + "name": "pointer_color", + "value": "#007DFF" + }, + { + "name": "warn_color", + "value": "#FF595A" + }, + { + "name": "hint_color", + "value": "#007DFF" + }, + { + "name": "text_color", + "value": "#182431" + } + ] +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json new file mode 100644 index 0000000..2375b2d --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + }, + { + "name": "title", + "value": "录音机" + }, + { + "name": "search_recording_files", + "value": "搜索录音文件" + }, + { + "name": "mark", + "value": "标记" + }, + { + "name": "pause", + "value": "暂停" + }, + { + "name": "continue_record", + "value": "继续" + }, + { + "name": "predict_hint", + "value": "预计还能录制10小时以上" + }, + { + "name": "delete_hint", + "value": "是否删除此条录音?" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "delete", + "value": "删除" + }, + { + "name": "has_call_hint", + "value": "通话状态无法录音" + }, + { + "name": "recording_hint", + "value": "录音机正在录音" + }, + { + "name": "suspend_record_hint", + "value": "录音机暂停录音" + } + ] +} diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/bg_record.png new file mode 100644 index 0000000000000000000000000000000000000000..41c12ccb5bb90cd9c05508690ca0b88f33e96008 GIT binary patch literal 3806 zcmdUx2~bnl8pm&BS5adC7Z5~>5L6UdB&-z>DkwaWML?iHA+kjRN!X!QL|N6MD42i* zNkBA$VGZKKs>CG5Kp=!Q2m}Zqpe(Yaw4Kf?4?EMD&YOAf+&Oda{hxFHzwbNe%$-lz zA?yRTSzDg81VA7F0IgntkPDcvzWuZItI0oeSp8b~5&%mAG!R?_v=7(-28n<{!UjNL zHAs=)yn#O&NJ3IfN>qH~>ZsMW)g(ZoBAXyZ@uqj(tb9cd2}%YL;=kX=>GI_v(WDiur@FdIyO~h>DA> zj+uj3V~`L7ZIY4%iTys|SBMx`SzJQv_!+P5vPX5Cypiae*en8CO-cj|m;x(r0hB`DpGdzydeLHr7k|tdD79%Ir8U)OFEHjn z#?9V$lHBFfY$ON36BN%Huf&2#lO&3rFDc%@Eo1|q`t3TKuLwtmo`)^Jv_p0j@SH6N z)^Z9Gkk{ti4|kW;+ds>-=vI5$Zi+ip1w#4W|BBH%X=j)xY^6`FN?<>AARk$>hGSo+ z-w;i@GtuEy6u*s<> z3p&#JM2&guq@bKJY=Z#YcU}03(>h6fcYCK_e4#kV`MI+U>rzDVDUQXNPY1Hga83SY z5B-wLk_EivBD{JTAt}Y}^mK|fzNOf><*zpcDg;haPTz4IN(EEhLbAuwp^u7w+V;1j zQD~>fS4mA6$~?2?cLl9YyR{@;OL44Vv0`U{a|Zw3gIU+%nSx3{Gqr48R-1eMuSNC4 zXgFTB4-MBeXu4-KW|@)5+NS&E(cEL@a3bRECv*!Yz9V-ym%bdo!^dcj;={p)TSvT@ zg$kCrKPPh>Rn?7PLHY=R98Ia(BHv&*)6eWFJ1J_v#>$gr`3lFQi{w`^fq2N2shIzh z2pnuO%4yi{;bYm*$!Ql(oAy|YT=rB-hIZ{pxBMwo8(vcz%*Ow&xCSV_9R= z(g)s>T|SXyf+$ctNJ+}xd*sATTLl;`o(rAGf}2X!XThVteXdnVIg-=AFzyn93P@o4 zlN@qVac^ne|u25+A1zJ4u=O8po*_yqlk%Z_Xbbp4-P5 zUE%a`5ip~yHjCaYcPnEg$zK0(gu^}#e}@{KD~UDN~t7S7SeUC=?t z1gjRFIAh#^+5f0YC%+EjLiC0jz3umZR8vF@&e=P9TWhx5yI+g@GK0$+T3yw83cCn5 zwjF&mC-t*azjmJ^oZP|ca!;M<8M*Fci6nI zjOA7~Y&<4gzA?AliO65L#$h&cW|m@4qZ>P}pRjW`h3UV5@JGh3-z&251)bd_8(zE* zYbXof(HsVyz=q{EJ7B3U-?hwlazm0-AziMoM_*JVW$?DA`a_jva{NsD)3{miWlnt; zB?1>ho$l0!V|v+a#g#2pao8Zm|J=Ff&tqOzOJf$|u8?8WR@EFLP0s8vbyMV0lPT>p zBbB0&p%l_I&UlP9S&~OC>!t7NuKrBE%0W#TS`99QnO^>W3Zue2+ipj2lcAZlPJ z*JSVc#G1&!p+i}8`=!KpDatzsuRMD|oUb#r-J(AIW}XDq5(1kMT~yNvy5bN=nBW#~%7*UeLr8QKJ&yG;En(eXf%qa9GzJ zQDN}P$As4%gV$`2sHNTN;nh)F2u&I(yPjP{O|pDs4oOW@|8e~-MMxD zSPA*dg}73S&nL8db6=SpKNZ?AK9cN{QQBb}i9$EnMfJwI22^;A({(w#D;~3CrewV> zf}Yc0?VyiUvZUQJ8JCaEeWPZ@Vpg`F-qI6&l*8FIJDq1Z`u?`t;jvHLiR0>t^!+A;Y`#FOnC&;eUzJ`!bTpW%#)ns+jaRsKvV47yB;9-HUy#x{Zy( zA7$MmYs{h)5L@t=Mo60sBQ9QaK}?GZsU$$tZJWJdgUoiYF~8R-`|+Kcury3Wo_r_6 zLPZ)@V-O97{)-n9E3X%{SQb1R{|!#b&a&5C$1qYrh5rEOwpa|B_|Fpmg6HvHP6$MAVKP4$llI;+cX@w}YKwSV%z1~5Fi7Ic*g2dvURZ*BkZC?>+jExyGu)Ffe8=j% z#a#Zs4@$ztK;vzxIzxgHfklD2^jN{IbBOV-WjHu9LN}#t+9E!CF3*1^NC@Orb;NrH zW_5r5(J9&_Oq@DKgifu!II_h5K>cF_2~_YWUc9@r8%Y}zF{w!r12*j3$`+=&g*>5YfC zQ;zM<1UIR4qh4U@rLCu9A*dYc`4v<}pBOXq$Mrtzm9=&8TF(DO{VnzmC}{k9eVX;> zy8Kyn(<42$yYjM2$k|iwQ`+ZrViRw^i;{3d80ghCv5WUe-!C`ok0@bfUk@ee;BX3? zNNs$aYA_*iI%;2XdCJKX;cg!qWf|p+V*r9#LwjIug}$42E4D^g&c-s>q-`TipKQiA zOR{$8R>!A>A8?cmxN>%`&0UiFBvEEq`chYh)j6_yhSk{pE5=4zenYdPv7twPQ(mb;I9 literal 0 HcmV?d00001 diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg new file mode 100644 index 0000000..6f7f039 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_back.svg @@ -0,0 +1,10 @@ + + + systemicon/back + + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg new file mode 100644 index 0000000..3ec94e4 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_add.svg @@ -0,0 +1,8 @@ + + + ic_clock_add + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg new file mode 100644 index 0000000..14a0ba5 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_enhance.svg @@ -0,0 +1,10 @@ + + + ic_clock_enhance + + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg new file mode 100644 index 0000000..330eda7 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_mark.svg @@ -0,0 +1,8 @@ + + + ic_clock_mark + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg new file mode 100644 index 0000000..4a6c569 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_play.svg @@ -0,0 +1,7 @@ + + + ic_clock_play + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg new file mode 100644 index 0000000..c8f7906 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_record.svg @@ -0,0 +1,7 @@ + + + ic_clock_record + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg new file mode 100644 index 0000000..0296449 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_stop.svg @@ -0,0 +1,7 @@ + + + ic_clock_stop + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg new file mode 100644 index 0000000..bf6f0ea --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_clock_suspend.svg @@ -0,0 +1,8 @@ + + + ic_clock_suspend + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg new file mode 100644 index 0000000..34c0e94 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_play.svg @@ -0,0 +1,8 @@ + + + ic_record_play + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg new file mode 100644 index 0000000..1b2a8aa --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_search.svg @@ -0,0 +1,8 @@ + + + ic_record_search + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg new file mode 100644 index 0000000..2b7ceaa --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/ic_record_stop.svg @@ -0,0 +1,9 @@ + + + ic_record_stop + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg new file mode 100644 index 0000000..400c3ef --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/oh_modules/@ohos/common/src/main/resources/base/media/public_more.svg @@ -0,0 +1,13 @@ + + + public_more + + + + + + + + + + \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/package.json b/product/tablet/oh_modules/@ohos/recorder/package.json new file mode 100644 index 0000000..83c74cf --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/package.json @@ -0,0 +1,16 @@ +{ + "license": "ISC", + "types": "", + "devDependencies": {}, + "name": "@ohos/recorder", + "description": "a npm package which contains arkUI2.0 page", + "ohos": { + "org": "" + }, + "main": "src/main/ets/components/MainPage/MainPage.ets", + "repository": {}, + "version": "1.0.0", + "dependencies": { + "@ohos/common": "file:../../common" + } +} diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets new file mode 100644 index 0000000..2b1cae6 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/AudioController.ets @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 mediaLibrary from '@ohos.multimedia.mediaLibrary'; +import media from '@ohos.multimedia.media'; +import { LogUtil } from '@ohos/common'; +import { BusinessError, Callback } from '@ohos.base' + +export enum AudioState { + /** + * The initial state + */ + IDLE, + /** + * Continuously update time starting from IDLE state or PAUSED state + */ + RUNNING, + /** + * Click Pause from the RUNNING state + */ + PAUSED, +} + +const NOTIFY_INTERVAL_MS = 50; +const TAG = "AudioController : "; + +export class AudioController { + private audioPlayer?: media.AVPlayer; + private state: string = 'idle'; + private playFile: string = ''; + private dataLoad: boolean = false; + private currentTimeMs: number = 0; + private intervalId: number = -1; + private timeUpdateListener?: Callback; + private stateUpdateListener?: Callback; + + /** + * Set the time update listener + * + * @param listener + */ + public setTimeUpdateListener(tag: string, timeUpdateListener: Callback): void { + LogUtil.info(`${TAG} setTimeUpdateListener`); + this.timeUpdateListener = timeUpdateListener; + } + + /** + * Set the status update listener + * + * @param listener + */ + public setStateUpdateListener(tag: string, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; + } + + /** + * Notification time update + */ + private notifyTimeChanges() { + if (this.timeUpdateListener) { + this.timeUpdateListener(this.currentTimeMs); + } + } + + /** + * Notification of status updates + */ + private async notifyStateChanges() { + if (this.stateUpdateListener) { + LogUtil.info(`${TAG} state update ${this.state}`); + this.stateUpdateListener(this.state); + } + } + + /** + * Initialize the audio player + * + * @param playSrc + * @param callback + */ + async initAudioPlayer(playSrc: string, callback: () => void) { + LogUtil.info(`${TAG} initAudioPlayer`); + this.playFile = playSrc; + this.dataLoad = false; + this.release(); + LogUtil.info(`${TAG} createAudioPlayer`); + if (!this.audioPlayer) { + return; + } + try { + this.audioPlayer = await media.createAVPlayer(); + } catch (e) { + } + this.audioPlayer?.on('stateChange', this.stateChangeListener) + } + + private stateChangeListener = async (state: string, reason: media.StateChangeReason) => { + if (!this.audioPlayer) { + return; + } + this.state = state; + switch (state) { + case 'idle' : + break; + case 'initialized': + break; + case 'playing': + break; + case 'prepared': + break; + case 'paused': + break; + case 'completed': + break; + case 'stopped': + case 'released': + break; + } + } + /** + * audioPlayer play + */ + play() { + try { + if (this.audioPlayer) { + this.audioPlayer.play(); + } + } catch (e) { + } + } + + /** + * audioPlayer seek time + * + * @param timeMs + */ + seek(timeMs: number) { + if (this.audioPlayer) { + LogUtil.info(`${TAG} audioPlayer time to jump. time:` + timeMs); + this.audioPlayer.seek(timeMs); + } + } + + /** + * audioPlayer pause + */ + pause() { + if (this.audioPlayer) { + LogUtil.info(`${TAG} audioPlayer pause`); + this.audioPlayer.pause(); + } + } + + /** + * audioPlayer stop + */ + stop() { + if ((this.audioPlayer) && this.state != 'idle') { + LogUtil.info(`${TAG} audioPlayer stop`); + this.state = 'idle'; + this.audioPlayer.release(); + this.intervalId = -1; + } + } + + /** + * audioPlayer continue play + */ + continuePlay() { + if (this.audioPlayer) { + LogUtil.info(`${TAG} audioPlayer continue play`); + this.audioPlayer.play(); + } + } + + /** + * audioPlayer release + */ + release() { + if (this.audioPlayer) { + this.currentTimeMs = 0; + this.notifyTimeChanges(); + LogUtil.info(`${TAG} audioPlayer release`); + this.audioPlayer.release(); + this.audioPlayer = undefined; + } + } + +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets new file mode 100644 index 0000000..db8262d --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/MediaController.ets @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 mediaLibrary from '@ohos.multimedia.mediaLibrary'; +import { Util } from '@ohos/common'; +import { RecordData } from '../model/RecordData'; +import data_preferences from '@ohos.data.preferences'; +import { LogUtil } from '@ohos/common'; + +const TAG = 'MediaController : '; + +export class MediaController { + private mMediaLibrary: mediaLibrary.MediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext); + private preferences?: data_preferences.Preferences; + + constructor() { + this.initPreferences(); + } + + /** + * init Preferences + */ + async initPreferences() { + LogUtil.info(`${TAG} initPreferences.`); + this.preferences = await data_preferences.getPreferences(globalThis.abilityContext, 'myRecorderStore'); + } + + /** + * save File Duration to preferences + * + * @param name + * @param value + */ + async saveFileDuration(name: string, value: number) { + LogUtil.info(`${TAG} saveFileDuration. fileName : ${name}. duration:${value}`); + if (this.preferences) { + await this.preferences.put(name, value); + this.preferences.flush(); + LogUtil.info(`${TAG} save File Duration end.`); + } + } +} + +export default new MediaController(); \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets new file mode 100644 index 0000000..ec15a77 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/RecordController.ets @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 media from '@ohos.multimedia.media'; +import { LogUtil } from '@ohos/common'; +import Notification from '@ohos.notification'; +import { BusinessError, Callback } from '@ohos.base' + +const NOTIFY_INTERVAL_MS = 60; +const NOTIFY_ID = 10023; +const TAG = 'RecordController : '; + +export enum RecordState { + IDLE, + RUNNING, + PAUSED, +} + +export class RecordController { + private beforePauseTime: number = 0; + private startTimestamp: number = 0; + private notifierId: number = -1; + private state: string = ''; + private config?: media.AVRecorderConfig; + private openedFileFd?: number; + private currentFilePath?: string; + private recorderDuration: number = 0; + private currentTimeMs: number = 0; + private audioRecorder?: media.AVRecorder; + private timeUpdateListener?: Callback; + private stateUpdateListener?: Callback; + + /** + * Notification time update + */ + private notifyTimeChanges() { + if (this.timeUpdateListener) { + this.timeUpdateListener(this.currentTimeMs); + } + } + + /** + * Notification of status updates + */ + private async notifyStateChanges() { + if (this.stateUpdateListener) { + LogUtil.info(`${TAG} state update. ${this.state}`); + this.stateUpdateListener(this.state); + } + } + + /** + * Set the time update listener + * + * @param listener + */ + public setTimeUpdateListener(tag: string, timeUpdateListener: Callback): void { + LogUtil.info(`${TAG} setTimeUpdateListener`); + this.timeUpdateListener = timeUpdateListener; + } + + /** + * Set the status update listener + * + * @param listener + */ + public setStateUpdateListener(tag: string, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; + } + + /** + * init AudioRecorder + */ + async initAudioRecorder() { + LogUtil.info(`${TAG} initAudioRecorder.`); + if (!this.audioRecorder) { + this.audioRecorder = await media.createAVRecorder(); + } + this.setAVRecorderCallback(this.audioRecorder); + } + + private setAVRecorderCallback(avRecorder: media.AVRecorder): void { + if (!avRecorder) { + return; + } + avRecorder.on('error', async (err: BusinessError) => { + + }); + avRecorder.on('stateChange', async (state: string, resaon: media.StateChangeReason) => { + this.state = state; + switch (state) { + case 'idle': + break; + case 'initialized': + break; + case 'started': + break; + case 'prepared': + break; + case 'paused': + break; + case 'completed': + break; + case 'stopped': + break; + case 'released': + break; + case 'released': + break; + default: + break + } + }); + } + + /** + * Gets the sound size of the recording + */ + getSoundVolume() { //todo + return Math.random() * 100 + 5; + } + + /** + * Recorder start + * + * @param pathName + */ + startRecorder(tag: string, filefd: number, filePath: string, config: media.AVRecorderConfig, + recorderStateCallback: Callback, onErrorCallback?: Callback) { + if (this.audioRecorder) { + this.recorderDuration = 0; + this.currentFilePath = filePath; + this.config = config; + this.openedFileFd = filefd; + if (this.audioRecorder.state === 'idle') { + this.audioRecorder.prepare(config); + } else { + this.audioRecorder.reset(); + } + LogUtil.info(`${TAG} audioRecorder prepare.`); + ; + } else { + LogUtil.error(`${TAG} case failed, audioRecorder is null.`); + } + } + + /** + * Recorder pause + */ + pause() { + if (this.audioRecorder) { + LogUtil.info(`${TAG} audioRecorder pause`); + this.audioRecorder.pause(); + } + } + + /** + * Recorder resume + */ + resume() { + if (this.audioRecorder) { + LogUtil.info(`${TAG} audioRecorder resume`); + this.audioRecorder.resume(); + } + } + + /** + * Recorder stop + */ + stop() { + if (this.audioRecorder) { + LogUtil.info(`${TAG} audioRecorder stop`); + this.audioRecorder.stop(); + } + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets new file mode 100644 index 0000000..bf5bc9a --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/controller/StateController.ets @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { LogUtil } from '@ohos/common'; +import { BusinessError, Callback } from '@ohos.base' + +const TAG = 'ControlState : '; + +export enum ControlState { + START, + END, +} + +export class StateController { + private state: number = 1; + private stateUpdateListener?: Callback; + + /** + * Set the status update listener + * + * @param listener + */ + public setStateUpdateListener(tag: number, setStateUpdateListener: Callback): void { + LogUtil.info(`${TAG} setStateUpdateListener`); + this.stateUpdateListener = setStateUpdateListener; + } + + /** + * Notification of status updates + */ + private async notifyStateChanges() { + if (this.stateUpdateListener) { + this.stateUpdateListener(this.state); + } + } + + /** + * Announce the start of recording + */ + public start() { + LogUtil.info(`${TAG} record start.`); + this.state = ControlState.START; + this.notifyStateChanges(); + } + + /** + * Announce the end of recording + */ + public end() { + LogUtil.info(`${TAG} record end.`); + this.state = ControlState.END; + this.notifyStateChanges(); + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets new file mode 100644 index 0000000..ab6a485 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/ets/model/RecordData.ets @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2022 HiHope Open Source Organization. + * 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 { MediaController } from '../controller/MediaController'; +import mediaLibrary from '@ohos.multimedia.mediaLibrary'; + +export class RecordData { + fileAsset: string = ''; + title: string = ''; + duration: number = 0; + date: number = 0; + + constructor(fileAsset: number, date: number, title: string) { + if (fileAsset) { + if (fileAsset > 0) { + this.duration = fileAsset; + } else { + this.duration = 0; + } + if (date > 0) { + this.date = date; + } else { + this.date = 0; + } + this.title = title; + } else { + this.duration = 0; + this.title = ''; + } + } +} \ No newline at end of file diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/module.json5 b/product/tablet/oh_modules/@ohos/recorder/src/main/module.json5 new file mode 100644 index 0000000..ed1e039 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "recorder", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "uiSyntax": "ets" + } +} diff --git a/product/tablet/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json b/product/tablet/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/product/tablet/oh_modules/@ohos/recorder/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/product/tablet/src/main/ets/Application/MyAbilityStage.ts b/product/tablet/src/main/ets/Application/MyAbilityStage.ts index 0a9efc1..06ad1b3 100644 --- a/product/tablet/src/main/ets/Application/MyAbilityStage.ts +++ b/product/tablet/src/main/ets/Application/MyAbilityStage.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import AbilityStage from "@ohos.application.AbilityStage" +import AbilityStage from "@ohos.app.ability.AbilityStage" export default class MyAbilityStage extends AbilityStage { onCreate() { diff --git a/product/tablet/src/main/ets/MainAbility/MainAbility.ts b/product/tablet/src/main/ets/MainAbility/MainAbility.ts index 67501c1..a0be8b4 100644 --- a/product/tablet/src/main/ets/MainAbility/MainAbility.ts +++ b/product/tablet/src/main/ets/MainAbility/MainAbility.ts @@ -13,14 +13,13 @@ * limitations under the License. */ -import Ability from '@ohos.application.Ability' +import Ability from '@ohos.app.ability.Ability' import Notification from '@ohos.notification'; export default class MainAbility extends Ability { onCreate(want, launchParam) { console.log("[Demo] MainAbility onCreate") globalThis.abilityWant = want; - globalThis.abilityContext = this.context; } onDestroy() { @@ -31,17 +30,6 @@ export default class MainAbility extends Ability { onWindowStageCreate(windowStage) { // Main window is created, set main page for this ability console.log("[Demo] MainAbility onWindowStageCreate") - this.context.requestPermissionsFromUser(['ohos.permission.MICROPHONE', 'ohos.permission.WRITE_MEDIA', 'ohos.permission.READ_MEDIA']).then(() => { - Notification.requestEnableNotification().then(() => { - windowStage.loadContent("pages/index", (err, data) => { - if (err.code) { - console.error('Failed to load the content. Cause:' + JSON.stringify(err)); - return; - } - console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) - }); - }) - }) } onWindowStageDestroy() { diff --git a/product/tablet/src/main/ets/pages/RecordingPage.ets b/product/tablet/src/main/ets/pages/RecordingPage.ets index f352c8b..8f4da50 100644 --- a/product/tablet/src/main/ets/pages/RecordingPage.ets +++ b/product/tablet/src/main/ets/pages/RecordingPage.ets @@ -29,23 +29,11 @@ export struct RecordingPage { @State currentTime: number = 0 @State state: RecordState = RecordState.IDLE private recordController: RecordController = new RecordController() - @State fileAsset: mediaLibrary.FileAsset = undefined private stateController = new StateController() heightList: Array = [] async aboutToAppear() { - let that = this - this.recordController.setTimeUpdateListener((currentTimeMs: number) => { - if (Math.floor(currentTimeMs / (TIME_COUNT / 2 * 1000 * TIME_INTERVAL_S / VOICE_FREQUENCY)) - Math.floor(this.currentTime / (TIME_COUNT / 2 * 1000 * TIME_INTERVAL_S / VOICE_FREQUENCY)) == 1) { - that.heightList.splice(0, 1) - that.heightList.push(this.recordController.getSoundVolume()) - } - this.currentTime = currentTimeMs - }) - this.recordController.setStateUpdateListener((state) => { - this.state = state - }) - this.initHeightList() + } initHeightList() { @@ -77,7 +65,7 @@ export struct RecordingPage { Stack({ alignContent: Alignment.Top }) { Column() { Row() { - ForEach(Array.from(Array(TIME_COUNT + 1).keys()), (item) => { + ForEach(Array.from(Array(TIME_COUNT + 1).keys()), (item:number) => { Column() { Text(Util.timeFormat(((item - (TIME_COUNT - 1) / 2) * 1000 * TIME_INTERVAL_S + Math.floor(this.currentTime / (1000 * TIME_INTERVAL_S)) * (1000 * TIME_INTERVAL_S)), false)) .textAlign(TextAlign.Center) @@ -85,19 +73,19 @@ export struct RecordingPage { .fontSize($r("app.float.font_10")) .opacity($r("app.float.opacity_6")) Row() { - ForEach(Array.from(Array(5).keys()), (scaleItem) => { + ForEach(Array.from(Array(5).keys()), (scaleItem:number) => { Rect() .width($r("app.float.wh_value_1")) .fill($r("app.color.text_color")) .height(scaleItem == 2 ? $r("app.float.wh_value_10") : $r("app.float.wh_value_5")) .opacity(scaleItem == 2 ? $r("app.float.opacity_4") : $r("app.float.opacity_2")) - }, scaleItem => scaleItem) + }, (scaleItem:number) => scaleItem+'') }.width(ConfigData.WH_100_100) .alignItems(VerticalAlign.Top) .height($r("app.float.wh_value_10")) .justifyContent(FlexAlign.SpaceAround) }.width((100 / TIME_COUNT) + "%") - }, item => item) + }, (item:number) => item+'') } .offset({ x: (-(100 / TIME_COUNT) * (this.currentTime % (TIME_INTERVAL_S * 1000) / (TIME_INTERVAL_S * 1000))) + "%" @@ -106,13 +94,13 @@ export struct RecordingPage { Row() { Row() { Row() { - ForEach(Array.from(Array(VOICE_FREQUENCY).keys()), (item) => { + ForEach(Array.from(Array(VOICE_FREQUENCY).keys()), (item:number) => { Rect() .width($r("app.float.wh_value_1")) .fill($r("app.color.text_color")) .height(this.heightList[item] * 0.5) .opacity($r("app.float.opacity_2")) - }, item => item) + }, (item:number) => item+'') }.width(ConfigData.WH_100_100) .justifyContent(FlexAlign.SpaceAround) .offset({ @@ -189,20 +177,12 @@ export struct RecordingPage { if (this.state == RecordState.IDLE) { let hasCall = await call.hasCall() if (hasCall) { - prompt.showToast({ message: $r('app.string.has_call_hint') }) } else { this.stateController.start() this.recordController.initAudioRecorder() - this.fileAsset = await MediaController.createAudioFile() - let fd = await this.fileAsset.open('Rw') - this.recordController.startRecorder(`fd://${fd}`) } } else { - this.recordController.stop(() => { - this.initHeightList() - MediaController.saveFileDuration(this.fileAsset.title, this.currentTime) - this.stateController.end() - }) + this.recordController.stop() } }) diff --git a/product/tablet/src/main/ets/pages/recordList.ets b/product/tablet/src/main/ets/pages/recordList.ets index 9a5f73b..de99020 100644 --- a/product/tablet/src/main/ets/pages/recordList.ets +++ b/product/tablet/src/main/ets/pages/recordList.ets @@ -25,49 +25,12 @@ export struct recordList { private audioController: AudioController = new AudioController() @State state: AudioState = AudioState.IDLE; @State filterText: string = ""; - private deleteRecord: RecordData = undefined - private stateController = new StateController() - @State disable: boolean = false - confirm: () => void = () => { - MediaController.deleteRecord(this.deleteRecord.fileAsset.uri, () => { - for (let i = this.recordList.length - 1;i >= 0; i--) { - if (this.deleteRecord.fileAsset.uri == this.recordList[i].fileAsset.uri) { - this.recordList.splice(i, 1) - } - } - }) - } - dialogController: CustomDialogController = new CustomDialogController({ - builder: DeleteRecordDialog({ deleteRecordTitle: this.deleteRecord.title, confirm: this.confirm }), - autoCancel: true, - alignment: DialogAlignment.Bottom, - offset: { dy: -16, dx: 0 } - }) - - async getAudios() { - this.recordList = await MediaController.queryAllAudios() - } + //private deleteRecord: RecordData; + private stateController = new StateController(); + @State disable: boolean = false; aboutToAppear() { - this.getAudios() - this.stateController.setStateUpdateListener((state) => { - if (state == ControlState.START) { - this.disable = true - this.audioController.stop() - } else { - this.disable = false - this.getAudios() - } - }) - this.audioController.setTimeUpdateListener((currentTime: number) => { - this.currentTime = currentTime - }) - this.audioController.setStateUpdateListener((state: AudioState) => { - if (state == AudioState.IDLE) { - this.selectedIndex = -1 - } - this.state = state - }) + ; } build() { @@ -118,19 +81,17 @@ export struct recordList { Column() { List() { - ForEach([...this.recordList].reverse().map((value, index) => { - return { i: index, data: value } - }), (item) => { + ForEach([...this.recordList].reverse(), (item:RecordData, index:number) => { ListItem() { Column() { Row() { Column() { - Text(item.data.title) + Text(item.title) .fontColor($r("app.color.text_color")) .fontSize($r("app.float.font_16")) .width($r("app.float.wh_value_105")) .lineHeight($r("app.float.wh_value_10_5")) - Text(Util.getDateFormat(item.data.date)) + Text(Util.getDateFormat(item.date)) .fontColor($r("app.color.text_color")) .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_14")) @@ -139,12 +100,12 @@ export struct recordList { } Row() { - Text(Util.timeFormat(item.data.duration)) + Text(Util.timeFormat(item.duration)) .fontColor($r("app.color.text_color")) .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_14")) .margin({ right: $r("app.float.distance_2") }) - Image((item.i == this.selectedIndex && this.state == AudioState.RUNNING) ? $r("app.media.ic_record_stop") : $r("app.media.ic_record_play")) + Image((index == this.selectedIndex && this.state == AudioState.RUNNING) ? $r("app.media.ic_record_stop") : $r("app.media.ic_record_play")) .width($r("app.float.wh_value_12")) .height($r("app.float.wh_value_12")) } @@ -154,9 +115,9 @@ export struct recordList { .justifyContent(FlexAlign.SpaceBetween) .padding({ left: $r("app.float.distance_12"), right: $r("app.float.distance_12") }) .onClick(() => { - if (this.selectedIndex != item.i || this.state == AudioState.IDLE) { - this.selectedIndex = item.i - this.audioController.initAudioPlayer(item.data.fileAsset, () => { + if (this.selectedIndex != index || this.state == AudioState.IDLE) { + this.selectedIndex = index + this.audioController.initAudioPlayer(item.fileAsset, () => { this.audioController.play() }) } else if (this.state == AudioState.RUNNING) { @@ -169,17 +130,15 @@ export struct recordList { LongPressGesture() .onAction(() => { this.audioController.stop() - this.deleteRecord = item.data - this.dialogController.open() }) ) - if (this.selectedIndex == item.i) { + if (this.selectedIndex == index) { Column() { Slider({ value: this.currentTime, min: 0, - max: item.data.duration, + max: item.duration, style: SliderStyle.OutSet }) .trackThickness($r("app.float.wh_value_2")) @@ -199,7 +158,7 @@ export struct recordList { .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_10")) .margin({ right: $r("app.float.distance_2") }) - Text(Util.timeFormat(item.data.duration)) + Text(Util.timeFormat(item.duration)) .fontColor($r("app.color.text_color")) .opacity($r("app.float.opacity_6")) .fontSize($r("app.float.font_10")) @@ -214,8 +173,8 @@ export struct recordList { .width(ConfigData.WH_100_100) } } - }.visibility(item.data.title.indexOf(this.filterText) >= 0 ? Visibility.Visible : Visibility.None) - }, item => item.i) + }.visibility(item.title.indexOf(this.filterText) >= 0 ? Visibility.Visible : Visibility.None) + }, (index:number) => index+'') } .width(ConfigData.WH_100_100) @@ -244,8 +203,8 @@ export struct recordList { @CustomDialog struct DeleteRecordDialog { private controller: CustomDialogController - private deleteRecordTitle: string - private confirm: () => void + private deleteRecordTitle: string = ''; + private confirm: () =>void = ()=>{}; build() { Column() { diff --git a/product/tablet/src/main/module.json5 b/product/tablet/src/main/module.json5 index 6a30a37..fe25f59 100644 --- a/product/tablet/src/main/module.json5 +++ b/product/tablet/src/main/module.json5 @@ -2,7 +2,7 @@ "module": { "name": "tablet", "type": "entry", - "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "srcEntry": "./ets/Application/MyAbilityStage.ts", "description": "$string:tablet_desc", "mainElement": "MainAbility", "deviceTypes": [ @@ -15,7 +15,7 @@ "abilities": [ { "name": "MainAbility", - "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "srcEntry": "./ets/MainAbility/MainAbility.ts", "description": "$string:MainAbility_desc", "icon": "$media:icon", "label": "$string:MainAbility_label", @@ -35,15 +35,15 @@ } ], "requestPermissions": [ - { - "name": "ohos.permission.MICROPHONE" - }, - { - "name": "ohos.permission.WRITE_MEDIA" - }, - { - "name": "ohos.permission.READ_MEDIA" - } + //{ + // "name": "ohos.permission.MICROPHONE" + //}, + //{ + // "name": "ohos.permission.WRITE_MEDIA" + //}, + //{ + // "name": "ohos.permission.READ_MEDIA" + //} ] } } \ No newline at end of file -- Gitee