diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..32a9ae774052ac1503f4a573cca60bc5ca3bb4ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild +/entry/.preview +.cxx +/node_modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..213a04d9879a28c4db9ec544b8ded775b0ea2beb --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +BSD License + +Copyright (C) 2022 Huawei Device Co., Ltd. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +Neither the name of Hamcrest nor the names of its contributors may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/OAT.xml b/OAT.xml new file mode 100644 index 0000000000000000000000000000000000000000..4d6e6bccaeeb568be9abeba18dd0c2db218c2a66 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/README.OpenSource b/README.OpenSource new file mode 100644 index 0000000000000000000000000000000000000000..1c4f51e612598f7f9eaab0d1604fbd5e8111a681 --- /dev/null +++ b/README.OpenSource @@ -0,0 +1,11 @@ +[ + { + "Name": "JavaHamcrest", + "License": "BSD License", + "License File": " LICENSE ", + "Version Number": "2.2", + "Owner" : "Hamcrest" + "Upstream URL": "https://github.com/hamcrest/JavaHamcrest", + "Description": "Java (and original) version of Hamcrest" + } +] \ No newline at end of file diff --git a/README.md b/README.md index 8e5e5e3da92992301dea7aec0c9ed76a41b73a1e..451c4e2643d6c6a75772148e4d64f3749b739310 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,72 @@ -# Hamcrest +# hamcrest -#### 介绍 -{**以下是 Gitee 平台说明,您可以替换此简介** -Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 -无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} +## 简介 +> hamcrest是匹配器库,可以组合起来匹配。 -#### 软件架构 -软件架构说明 +![operation.png](screenshots/operation.png) +## 下载安装 +```shell +npm install @ohos/hamcrest --save +``` +OpenHarmony npm环境配置等更多内容,请参考 [如何安装OpenHarmony npm包](https://gitee.com/openharmony-tpc/docs/blob/master/OpenHarmony_npm_usage.md) 。 -#### 安装教程 +## 使用说明 +1. 引入文件及代码依赖 + ``` + import {AllOf} from '@ohos/hamcrest' + ``` -1. xxxx -2. xxxx -3. xxxx +2. 构建匹配器 + ``` + let matcher = AllOf.allOfMatches(StringContains.containsString('expected'), StringContains.containsString('value')) + ``` -#### 使用说明 +3. 调用匹配器匹配 + ``` + allOf() { + let matcher = AllOf.allOfMatches(StringContains.containsString('expected'), StringContains.containsString('value')) + console.info("allOf: " + matcher.matches('expected value')) + console.info("allOf: " + matcher.matches('value expected')) + console.info("allOf: " + matcher.matches('expected valu')) + } + ``` -1. xxxx -2. xxxx -3. xxxx +## 接口说明 -#### 参与贡献 +1. 匹配所有`AllOf.allOf()` +2. 匹配某一个`AnyOf.AnyOf()` +3. 匹配每一个`Every.everyItem()` +4. 匹配任意`IsAnything.anything()` +5. 匹配不是`IsNot.not()` +6. 匹配null`IsNull.nullValue()` +7. 匹配包含字符串`StringContains.containsString()` +8. 匹配以字符串结尾`StringEndsWith.endsWith()` +9. 匹配以字符串开头`StringStartsWith.startsWith()` +10. 匹配空字符串`IsEmptyString.emptyString()` -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +## 兼容性 +支持 OpenHarmony API version 8 及以上版本。 +## 目录结构 +```` +|---- hamcrest +| |---- entry # 示例代码文件夹 +| |---- hamcrest # hamcrest库文件夹 +| |---- index.ets # 对外接口 +| |---- src +| |---- main +| |---- components +| |---- core # 核心文件夹 +| |---- Every.ets # 匹配每一个 +| |---- AllOf.ets # 匹配所有 +| |---- IsAnything.ets # 匹配任意 +| |---- StringContains.ets # 匹配包含字符串 +| |---- README.md # 安装使用方法 +```` -#### 特技 +## 贡献代码 +使用过程中发现任何问题都可以提 [Issue](https://gitee.com/hihopeorg/Hamcrest/issues) 给我们,当然,我们也非常欢迎你给我们发 [PR](https://gitee.com/hihopeorg/Hamcrest/pulls) 。 -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) +## 开源协议 +本项目基于 [BSD License](https://gitee.com/hihopeorg/Hamcrest/blob/master/LICENSE) ,请自由地享受和参与开源。 \ No newline at end of file diff --git a/build-profile.json5 b/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7ea9d738214a7eb5dde21b3b6a64c4dbe35ae5e6 --- /dev/null +++ b/build-profile.json5 @@ -0,0 +1,31 @@ +{ + "app": { + "signingConfigs": [], + "compileSdkVersion": 8, + "compatibleSdkVersion": 8, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "hamcrest", + "srcPath": "./hamcrest" + } + ] +} \ No newline at end of file diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000000000000000000000000000000000000..e43494eec85130654bd74c3766e9ca1775e408da --- /dev/null +++ b/changelog.md @@ -0,0 +1,3 @@ +# 1.0.0 + + 1. 匹配器库功能实现,可以组合起来匹配 \ No newline at end of file diff --git a/entry/.gitignore b/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..88985e5e3db0cc0c4ebc5727b03ccd795723faa8 --- /dev/null +++ b/entry/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild +/entry/.preview +.cxx +/node_modules \ No newline at end of file diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ae58d1d0a70c602c9cfe1909b00dfec899ba1944 --- /dev/null +++ b/entry/build-profile.json5 @@ -0,0 +1,13 @@ +{ + "apiType": 'faMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/entry/hvigorfile.js b/entry/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..bcec4c99653062cbf17702c40a2dd2a7b809b81a --- /dev/null +++ b/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyHapTasks diff --git a/entry/package-lock.json b/entry/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..850210d5ceb6b6c00f30b9b441d9e71cd9389eaf --- /dev/null +++ b/entry/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "entry", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ohos/hamcrest": { + "version": "file:../hamcrest", + "requires": { + "assertion-error": "^1.1.0" + }, + "dependencies": { + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + } + } + } + } +} diff --git a/entry/package.json b/entry/package.json new file mode 100644 index 0000000000000000000000000000000000000000..92c8fcd995b201fd8884643dbe46308c5bb9ec38 --- /dev/null +++ b/entry/package.json @@ -0,0 +1,15 @@ +{ + "name": "entry", + "version": "1.0.0", + "ohos": { + "org": "huawei", + "buildTool": "hvigor", + "directoryLevel": "module" + }, + "description": "example description", + "repository": {}, + "license": "BSD License", + "dependencies": { + "@ohos/hamcrest": "file:../hamcrest" + } +} diff --git a/entry/src/main/config.json b/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..e58d7017530dd7b94fac517368fd4491974e19f4 --- /dev/null +++ b/entry/src/main/config.json @@ -0,0 +1,67 @@ +{ + "app": { + "bundleName": "com.example.hamcrest", + "vendor": "example", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.hamcrest", + "name": ".MyApplication", + "mainAbility": ".MainAbility", + "srcPath": "", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry", + "installationFree": false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "visible": true, + "srcPath": "MainAbility", + "name": ".MainAbility", + "srcLanguage": "ets", + "icon": "$media:icon", + "description": "$string:description_mainability", + "formsEnabled": false, + "label": "$string:entry_MainAbility", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "mode": { + "syntax": "ets", + "type": "pageAbility" + }, + "pages": [ + "pages/index" + ], + "name": ".MainAbility", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} \ No newline at end of file diff --git a/entry/src/main/ets/MainAbility/app.ets b/entry/src/main/ets/MainAbility/app.ets new file mode 100644 index 0000000000000000000000000000000000000000..1325479f3eacb26f709b33a5fc7b3f8b2a37fab5 --- /dev/null +++ b/entry/src/main/ets/MainAbility/app.ets @@ -0,0 +1,23 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD +* +* 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 { + onCreate() { + console.info('Application onCreate') + }, + onDestroy() { + console.info('Application onDestroy') + }, +} \ No newline at end of file diff --git a/entry/src/main/ets/MainAbility/pages/index.ets b/entry/src/main/ets/MainAbility/pages/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..2fe995efaec6e8581bdea9ee2814c7d71efcc955 --- /dev/null +++ b/entry/src/main/ets/MainAbility/pages/index.ets @@ -0,0 +1,434 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {HasProperty} from '@ohos/hamcrest' +import {StringContains} from '@ohos/hamcrest' +import {StringStartsWith} from '@ohos/hamcrest' +import {StringEndsWith} from '@ohos/hamcrest' +import {AllOf} from '@ohos/hamcrest' +import {AnyOf} from '@ohos/hamcrest' +import {IsNot} from '@ohos/hamcrest' +import {Is} from '@ohos/hamcrest' +import {IsEqual} from '@ohos/hamcrest' +import {IsNaN} from '@ohos/hamcrest' +import {IsEqualIgnoringCase} from '@ohos/hamcrest' +import {CharSequenceLength} from '@ohos/hamcrest' +import {IsBlankString} from '@ohos/hamcrest' +import {OrderingComparison} from '@ohos/hamcrest' +import {IsCloseTo} from '@ohos/hamcrest' +import {IsNull} from '@ohos/hamcrest' +import {IsArray} from '@ohos/hamcrest' +import {IsIn} from '@ohos/hamcrest' +import {MatchesPattern} from '@ohos/hamcrest' +import {Every} from '@ohos/hamcrest' + +@Entry +@Component +struct Index { + scroller: Scroller = new Scroller() + + hasProperty() { + let matcher = HasProperty.hasProperty('name') + console.info("hasProperty: " + matcher.matches({ name: 'Joe' })) + console.info("hasProperty: " + matcher.matches({ name: 'Joel' })) + console.info("hasProperty: " + matcher.matches({ age: 19 })) + } + + hasLength() { + let matcher = CharSequenceLength.hasLength(4); + console.info("hasLength: " + matcher.matches('aaaa')) + console.info("hasLength: " + matcher.matches('aaa')) + console.info("hasLength: " + matcher.matches('aa a')) + } + + anyOf() { + let matcherAnyOf = AnyOf.anyOfMatches(IsBlankString.blankString(), + IsEqualIgnoringCase.equalToIgnoringCase('aaa')) + console.log('anyOf: enter matcherAnyOf:' + matcherAnyOf.matches('AAA')) + console.log('anyOf: enter matcherAnyOf:' + matcherAnyOf.matches('bbb')) + console.log('anyOf: enter matcherAnyOf:' + matcherAnyOf.matches('')) + console.log('anyOf: enter matcherAnyOf:' + matcherAnyOf.matches('\n\r\t')) + } + + containsString() { + let matcher = StringContains.containsString('rat') + console.info("containsString: " + matcher.matches('jim the rat')) + console.info("containsString: " + matcher.matches('jim the rats')) + let matcher2 = StringContains.containsString('rats'); + console.info("containsString: " + matcher2.matches('jim the rat')) + } + + allOf() { + let matcher = AllOf.allOfMatches(StringContains.containsString('expected'), StringContains.containsString('value')) + console.info("allOf: " + matcher.matches('expected value')) + console.info("allOf: " + matcher.matches('value expected')) + console.info("allOf: " + matcher.matches('expected valu')) + } + + endsWith() { + let matcher = StringEndsWith.endsWith('test') + console.info("isArray: " + matcher.matches('aaabbbtest')) + console.info("isArray: " + matcher.matches('aaabbbtests')) + console.info("isArray: " + matcher.matches('testdjsdojw')) + } + + isNaN() { + let matcher = IsNaN.notANumber() + console.info("isNaN: " + matcher.matches(7)) + console.info("isNaN: " + matcher.matches(7.7)) + console.info("isNaN: " + matcher.matches(NaN)) + } + + isEqual() { + const value = [1, 2] + let matcher = IsEqual.equalTo(value) + console.info("isEqual: " + matcher.matches([1, 3])) + console.info("isEqual: " + matcher.matches([1, 2])) + let matcher2 = IsEqual.equalTo("string value") + console.info("isEqual: " + matcher2.matches("string value")) + console.info("isEqual: " + matcher2.matches("string values")) + } + + equalIgnoringCase() { + let matcher = IsEqualIgnoringCase.equalToIgnoringCase('Hello') + console.log('equalIgnoringCase:' + matcher.matches('heLLo')) + console.log('equalIgnoringCase:' + matcher.matches('hello')) + console.log('equalIgnoringCase:' + matcher.matches('HELLO')) + } + + orderingComparison() { + let matcher = OrderingComparison.greaterThan(5) + console.log('equalIgnoringCase:' + matcher.matches('6')) + console.log('equalIgnoringCase:' + matcher.matches('4')) + console.log('equalIgnoringCase:' + matcher.matches('5')) + + let matcher2 = OrderingComparison.greaterThanOrEqualTo(5) + console.log('equalIgnoringCase:' + matcher2.matches('6')) + console.log('equalIgnoringCase:' + matcher2.matches('4')) + console.log('equalIgnoringCase:' + matcher2.matches('5')) + + let matcher3 = OrderingComparison.lessThan(5) + console.log('equalIgnoringCase:' + matcher3.matches('6')) + console.log('equalIgnoringCase:' + matcher3.matches('4')) + console.log('equalIgnoringCase:' + matcher3.matches('5')) + + let matcher4 = OrderingComparison.lessThanOrEqualTo(5) + console.log('equalIgnoringCase:' + matcher4.matches('6')) + console.log('equalIgnoringCase:' + matcher4.matches('4')) + console.log('equalIgnoringCase:' + matcher4.matches('5')) + } + + isBlackString() { + let matcher = IsBlankString.blankString(); + console.log('isBlackString :' + matcher.matches('')) + console.log('isBlackString :' + matcher.matches('\n\r\t')) + + let matcher2 = IsBlankString.blankOrNullString(); + console.log('isBlackString: enter matcher2:' + matcher2.matches('\n\r\t')) + console.log('isBlackString: enter matcher2:' + matcher2.matches('null')) + console.log('isBlackString: enter matcher2:' + matcher2.matches(null)) + } + + isCloseTo() { + let matcher = IsCloseTo.closeTo(1.1, 0.0); + console.log('IsCloseTo :' + matcher.matches(1.10)) + + let matcher2 = IsCloseTo.closeTo(1.111111111, 0.0); + console.log('IsCloseTo :' + matcher.matches(1.1111111112)) + } + + isNull() { + let matcher = IsNull.nullValue() + console.log('isNull :' + matcher.matches(null)) + console.log('isNull :' + matcher.matches('null')) + console.log('isNull :' + matcher.matches('')) + } + + combinationMatch() { + let matcher = IsNot.not(StringContains.containsString('expected')); + console.info("combinationMatch: " + matcher.matches("expected value")) + console.info("combinationMatch: " + matcher.matches('another value')) + + let match = Is.is(StringStartsWith.startsWith('hamjest')) + console.info("combinationMatch: " + match.matches('hamjest is awesome')) + } + + isArray() { + let matcher = IsArray.array(IsEqual.equalTo('a'), IsEqual.equalTo('b'), IsEqual.equalTo('c')) + console.info("isArray: " + matcher.matches(['a', 'b', 'c'])) + console.info("isArray: " + matcher.matches(['a', 'd', 'b'])) + console.info("isArray: " + matcher.matches(['a', 'b'])) + } + + isIn() { + let matcher = IsIn.isIn(["bar", "foo"]) + console.info("isIn: " + matcher.matches("bar")) + console.info("isIn: " + matcher.matches(["bar", "foo"])) + + } + + every() { + let matcher = Every.everyItem(StringContains.containsString('a')) + console.info("every: " + matcher.matches(["AaA", "BaB", "CaC"])) + console.info("every: " + matcher.matches(["AAA", "BaB", "CbC"])) + } + + matchesPattern() { + let matcher = MatchesPattern.matchesPattern(new RegExp('bb')) + console.info("matchesPattern: " + matcher.matches('aabbcc')) + console.info("matchesPattern: " + matcher.matches('aabcc')) + console.info("matchesPattern: " + matcher.matches('abc')) + } + + build() { + + Stack({ alignContent: Alignment.TopStart }) { + Scroll(this.scroller) { + Column() { + Button() { + Text('hasProperty') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.hasProperty.bind(this)) + + Button() { + Text('hasLength') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + this.hasLength() + }) + + Button() { + Text('anyOf') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.anyOf.bind(this)) + + Button() { + Text('containsString') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.containsString.bind(this)) + + Button() { + Text('allOf') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.allOf.bind(this)) + + Button() { + Text('endsWith') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.endsWith.bind(this)) + + Button() { + Text('isNaN') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isNaN.bind(this)) + + Button() { + Text('isEqual') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isEqual.bind(this)) + + Button() { + Text('IsEqualIgnoringCase') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.equalIgnoringCase.bind(this)) + + Button() { + Text('orderingComparison') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.orderingComparison.bind(this)) + + Button() { + Text('isBlackString') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isBlackString.bind(this)) + + Button() { + Text('isCloseTo') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isCloseTo.bind(this)) + + Button() { + Text('isNull') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isNull.bind(this)) + + Button() { + Text('combinationMatch') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.combinationMatch.bind(this)) + + Button() { + Text('IsArray') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isArray.bind(this)) + + Button() { + Text('IsIn') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.isIn.bind(this)) + + Button() { + Text('every') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.every.bind(this)) + + Button() { + Text('matchesPattern') + .fontSize(25) + .fontWeight(FontWeight.Bold) + .padding({ left: 16, right: 16 }) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(this.matchesPattern.bind(this)) + + }.width('100%') + } + .scrollable(ScrollDirection.Vertical).scrollBar(BarState.On) + .scrollBarColor(Color.Gray).scrollBarWidth(1) + .onScroll((xOffset: number, yOffset: number) => { + console.info(xOffset + ' ' + yOffset) + }) + .onScrollEdge((side: Edge) => { + console.info('To the edge') + }) + .onScrollEnd(() => { + console.info('Scroll Stop') + }) + + }.width('100%').height('100%') + } +} \ No newline at end of file diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..b93f540e29265a34f883a977c442fa85349b94ca --- /dev/null +++ b/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "entry_MainAbility", + "value": "entry_MainAbility" + }, + { + "name": "description_mainability", + "value": "eTS_Empty Ability" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/base/media/icon.png b/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/entry/src/main/resources/base/media/icon.png differ diff --git a/hamcrest/.gitignore b/hamcrest/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4f9a973815d0b5e49bc8547681a6b4bc7a178d12 --- /dev/null +++ b/hamcrest/.gitignore @@ -0,0 +1,3 @@ +/node_modules +/.preview +/build \ No newline at end of file diff --git a/hamcrest/build-profile.json5 b/hamcrest/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..107d8c761a767ae4bd6c3798021d9fad61751005 --- /dev/null +++ b/hamcrest/build-profile.json5 @@ -0,0 +1,5 @@ +{ + "apiType": "faMode", + "buildOption": { + } +} diff --git a/hamcrest/hvigorfile.js b/hamcrest/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..3a7c40cd644527fdf586c81b110e346329f38c9a --- /dev/null +++ b/hamcrest/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').legacyHarTasks + diff --git a/hamcrest/index.ets b/hamcrest/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..f5df621ceb53d3d10e707e7a6c8a36396e2ece8a --- /dev/null +++ b/hamcrest/index.ets @@ -0,0 +1,60 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { HasProperty } from './src/main/ets/components/beans/HasProperty' +export { ArrayMatching } from './src/main/ets/components/collection/ArrayMatching' +export { HasItemInArray } from './src/main/ets/components/collection/HasItemInArray' +export { IsArray } from './src/main/ets/components/collection/IsArray' +export { IsArrayWithSize } from './src/main/ets/components/collection/IsArrayWithSize' +export { IsIn } from './src/main/ets/components/collection/IsIn' +export { IsMapContaining } from './src/main/ets/components/collection/IsMapContaining' +export { IsMapWithSize } from './src/main/ets/components/collection/IsMapWithSize' +export { AllOf } from './src/main/ets/components/core/AllOf' +export { AnyOf } from './src/main/ets/components/core/AnyOf' +export { CombinableMatcher } from './src/main/ets/components/core/CombinableMatcher' +export { Every } from './src/main/ets/components/core/Every' +export { Is } from './src/main/ets/components/core/Is' +export { IsAnything } from './src/main/ets/components/core/IsAnything' +export { IsEqual } from './src/main/ets/components/core/IsEqual' +export { IsInstanceOf } from './src/main/ets/components/core/IsInstanceOf' +export { IsIterableContaining } from './src/main/ets/components/core/IsIterableContaining' +export { IsNot } from './src/main/ets/components/core/IsNot' +export { IsNull } from './src/main/ets/components/core/IsNull' +export { IsSame } from './src/main/ets/components/core/IsSame' +export { ShortcutCombination } from './src/main/ets/components/core/ShortcutCombination' +export { StringContains } from './src/main/ets/components/core/StringContains' +export { StringEndsWith } from './src/main/ets/components/core/StringEndsWith' +export { StringRegularExpression } from './src/main/ets/components/core/StringRegularExpression' +export { StringStartsWith } from './src/main/ets/components/core/StringStartsWith' +export { SubstringMatcher } from './src/main/ets/components/core/SubstringMatcher' +export { ArrayIterator } from './src/main/ets/components/internal/ArrayIterator' +export { NullSafety } from './src/main/ets/components/internal/NullSafety' +export { SelfDescribingValue } from './src/main/ets/components/internal/SelfDescribingValue' +export { SelfDescribingValueIterator } from './src/main/ets/components/internal/SelfDescribingValueIterator' +export { IsCloseTo } from './src/main/ets/components/number/IsCloseTo' +export { IsNaN } from './src/main/ets/components/number/IsNaN' +export { OrderingComparison } from './src/main/ets/components/number/OrderingComparison' +export { CharSequenceLength } from './src/main/ets/components/text/CharSequenceLength' +export { IsBlankString } from './src/main/ets/components/text/IsBlankString' +export { IsEmptyString } from './src/main/ets/components/text/IsEmptyString' +export { IsEqualCompressingWhiteSpace } from './src/main/ets/components/text/IsEqualCompressingWhiteSpace' +export { IsEqualIgnoringCase } from './src/main/ets/components/text/IsEqualIgnoringCase' +export { MatchesPattern } from './src/main/ets/components/text/MatchesPattern' +export { MatcherAssert } from './src/main/ets/components/MatcherAssert' +export { CustomMatcher } from './src/main/ets/components/CustomMatcher' +export { BaseMatcher } from './src/main/ets/components/BaseMatcher' +export { DiagnosingMatcher } from './src/main/ets/components/DiagnosingMatcher' +export { FeatureMatcher } from './src/main/ets/components/FeatureMatcher' +export { BaseDescription } from './src/main/ets/components/BaseDescription' diff --git a/hamcrest/package-lock.json b/hamcrest/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..b4c98191668f663ecdfd6450ba9a413b121a52a8 --- /dev/null +++ b/hamcrest/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "@ohos/hamcrest", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + } + } +} diff --git a/hamcrest/package.json b/hamcrest/package.json new file mode 100644 index 0000000000000000000000000000000000000000..21ac266f76ec57bb6ef356981e3960242c0743bc --- /dev/null +++ b/hamcrest/package.json @@ -0,0 +1,22 @@ +{ + "name": "@ohos/hamcrest", + "description": "可组合使用的匹配器库", + "ohos": { + "org": "" + }, + "version": "1.0.0", + "main": "index.ets", + "types": "", + "repository": "https://gitee.com/hihopeorg/Hamcrest", + "license": "BSD License", + "dependencies": { + "assertion-error": "^1.1.0" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "hamcrest" + ], + "author": "hihope" +} diff --git a/hamcrest/src/main/config.json b/hamcrest/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..319b58b40010617213d738618c3779bd2aeb9f22 --- /dev/null +++ b/hamcrest/src/main/config.json @@ -0,0 +1,23 @@ +{ + "app": { + "bundleName": "com.example.hamcrest", + "vendor": "example", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.hamcrest", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "hamcrest", + "moduleType": "har" + }, + "uiSyntax": "ets" + } +} diff --git a/hamcrest/src/main/ets/components/BaseDescription.ets b/hamcrest/src/main/ets/components/BaseDescription.ets new file mode 100644 index 0000000000000000000000000000000000000000..de9067f70baea1b3757dba5d622b9937bd1ffef7 --- /dev/null +++ b/hamcrest/src/main/ets/components/BaseDescription.ets @@ -0,0 +1,70 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { SelfDescribing } from './SelfDescribing' +import { Description } from './Description' +import { NullDescription } from './NullDescription' + +/** + * A {@link Description} that is stored as a string. + */ +export abstract class BaseDescription implements Description { + static NONE: Description = new NullDescription(); + + value = ''; + + public appendText(text): Description { + this.append(text) + return this; + } + + public appendDescriptionOf(value: SelfDescribing): Description { + value.describeTo(this); + return this; + } + + public appendValue(value: Object): Description { + if (value === undefined) { + this.append('undefined'); + } else if (value == null) { + this.append('null'); + } else if (value instanceof String) { + this.append('"' + value + '"'); + } else if (value instanceof Array) { + this.appendList('[', ', ', ']', value); + } else { + this.append(value.toString()) + } + return this; + } + + public appendValueList(start: String, separator: String, end: String, ... list: SelfDescribing[]): Description { + return this.appendList(start, separator, end, list); + } + + public appendList(start: String, separator: String, end: String, list: SelfDescribing[]): Description { + this.append(start); + for (let i = 0; i < list.length; i++) { + if (i > 0) { + this.append(separator); + } + this.appendDescriptionOf(list[i]); + } + this.append(end); + return this; + } + + protected abstract append(str: String): void; +} diff --git a/hamcrest/src/main/ets/components/BaseMatcher.ets b/hamcrest/src/main/ets/components/BaseMatcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..1644cef69774accb965d63bc1341ff733349c84d --- /dev/null +++ b/hamcrest/src/main/ets/components/BaseMatcher.ets @@ -0,0 +1,51 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Matcher } from './Matcher' +import { Description } from './Description' +import { StringDescription } from './StringDescription' + +/** + * BaseClass for all Matcher implementations. + * + * @see Matcher + */ +export abstract class BaseMatcher implements Matcher { + public describeMismatch(item: Object, description: Description): void { + description.appendText("was ").appendValue(item); + } + + public toString(): String { + return StringDescription.convertToString(this); + } + + /** + * Useful null-check method. Writes a mismatch description if the actual object is null + * @param actual the object to check + * @param mismatch where to write the mismatch description, if any + * @return false iff the actual object is null + */ + protected static isNotNull(actual: Object, mismatch: Description): boolean { + if (actual == null) { + mismatch.appendText("was null"); + return false; + } + return true; + } + + public abstract matches(actual: Object): boolean; + + public abstract describeTo(description: Description): void; +} diff --git a/hamcrest/src/main/ets/components/CustomMatcher.ets b/hamcrest/src/main/ets/components/CustomMatcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..7edc6775e3fef0d05f6a0391020c2c90aae56afe --- /dev/null +++ b/hamcrest/src/main/ets/components/CustomMatcher.ets @@ -0,0 +1,32 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {BaseMatcher} from './BaseMatcher' +import {Description} from './Description' + +export abstract class CustomMatcher extends BaseMatcher { + private fixedDescription: String; + + public CustomMatcher(description: String) { + if (description == null) { + throw new Error("Description should be non null!"); + } + this.fixedDescription = description; + } + + public describeTo(description: Description): void { + description.appendText(this.fixedDescription); + } +} diff --git a/hamcrest/src/main/ets/components/Description.ets b/hamcrest/src/main/ets/components/Description.ets new file mode 100644 index 0000000000000000000000000000000000000000..6402406155e23b9f40196692ce6b8a4ef702de94 --- /dev/null +++ b/hamcrest/src/main/ets/components/Description.ets @@ -0,0 +1,85 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { SelfDescribing } from './SelfDescribing' +import { NullDescription } from './NullDescription' + +/** + * A description of a Matcher. A Matcher will describe itself to a description + * which can later be used for reporting. + * + * @see Matcher#describeTo(Description) + */ +export interface Description { + + /** + * Appends some plain text to the description. + * + * @param text + * the text to append. + * @return the update description when displaying the matcher error. + */ + appendText(text: String): Description; + + /** + * Appends the description of a {@link SelfDescribing} value to this description. + * + * @param value + * the value to append. + * @return the update description when displaying the matcher error. + */ + appendDescriptionOf(value: SelfDescribing): Description; + + /** + * Appends an arbitrary value to the description. + * + * @param value + * the object to append. + * @return the update description when displaying the matcher error. + */ + appendValue(value: Object): Description; + + /** + * Appends a list of values to the description. + * + * @param + * the description type. + * @param start + * the prefix. + * @param separator + * the separator. + * @param end + * the suffix. + * @param values + * the values to append. + * @return the update description when displaying the matcher error. + */ + appendValueList(start: String, separator: String, end: String, ... list: SelfDescribing[]): Description; + + /** + * Appends a list of SelfDescribing objects + * to the description. + * @param start + * the prefix. + * @param separator + * the separator. + * @param end + * the suffix. + * @param values + * the values to append. + * @return the update description when displaying the matcher error. + */ + appendList(start: String, separator: String, end: String, list: SelfDescribing[]): Description; +} diff --git a/hamcrest/src/main/ets/components/DiagnosingMatcher.ets b/hamcrest/src/main/ets/components/DiagnosingMatcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..ee0dd99def9a9788c74b61443d3efe6fc93a9c3e --- /dev/null +++ b/hamcrest/src/main/ets/components/DiagnosingMatcher.ets @@ -0,0 +1,36 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseMatcher } from './BaseMatcher' +import { Description } from './Description' +import { BaseDescription } from './BaseDescription' + +/** + * TODO(ngd): Document. + * + * @param the type of matcher being diagnosed. + */ +export abstract class DiagnosingMatcher extends BaseMatcher { + + public matches(item: Object): boolean { + return this.matchesWithDiagnosingMatcher(item, BaseDescription.NONE); + } + + public describeMismatch(item: Object, mismatchDescription: Description): void { + this.matchesWithDiagnosingMatcher(item, mismatchDescription); + } + + protected abstract matchesWithDiagnosingMatcher(item: Object, mismatchDescription: Description): boolean; +} diff --git a/hamcrest/src/main/ets/components/FeatureMatcher.ets b/hamcrest/src/main/ets/components/FeatureMatcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..38d037558795f2950a5fd04868c66820315b9d9d --- /dev/null +++ b/hamcrest/src/main/ets/components/FeatureMatcher.ets @@ -0,0 +1,67 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {DiagnosingMatcher} from './DiagnosingMatcher' +import {Description} from './Description' +import {Matcher} from './Matcher' + +/** + * Supporting class for matching a feature of an object. Implement featureValueOf() + * in a subclass to pull out the feature to be matched against. + * + * @param The type of the object to be matched + * @param The type of the feature to be matched + */ +export abstract class FeatureMatcher extends DiagnosingMatcher { + + private subMatcher: Matcher ; + private featureDescription: String; + private featureName: String; + + /** + * Constructor + * @param subMatcher The matcher to apply to the feature + * @param featureDescription Descriptive text to use in describeTo + * @param featureName Identifying text for mismatch message + */ + public constructor(subMatcher: Matcher, featureDescription: String, featureName: String) { + super(); + this.subMatcher = subMatcher; + this.featureDescription = featureDescription; + this.featureName = featureName; + } + + /** + * Implement this to extract the interesting feature. + * @param actual the target object + * @return the feature to be matched + */ + protected abstract featureValueOf(actual: T): U; + + protected matchesWithDiagnosingMatcher(actual: T, mismatch: Description): boolean { + let featureValue: U = this.featureValueOf(actual); + if (!this.subMatcher.matches(featureValue)) { + mismatch.appendText(this.featureName).appendText(" "); + this.subMatcher.describeMismatch(featureValue, mismatch); + return false; + } + return true; + } + + public describeTo(description: Description): void { + description.appendText(this.featureDescription).appendText(" ") + .appendDescriptionOf(this.subMatcher); + } +} diff --git a/hamcrest/src/main/ets/components/Matcher.ets b/hamcrest/src/main/ets/components/Matcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..1e45d847324b43cf5bfde4f260f79795c6d9c693 --- /dev/null +++ b/hamcrest/src/main/ets/components/Matcher.ets @@ -0,0 +1,48 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {SelfDescribing} from './SelfDescribing' +import {Description} from './Description' + +export interface Matcher extends SelfDescribing { + + /** + * Evaluates the matcher for argument item. + * + * This method matches against Object, instead of the generic type T. This is + * because the caller of the Matcher does not know at runtime what the type is + * (because of type erasure with Java generics). It is down to the implementations + * to check the correct type. + * + * @param actual the object against which the matcher is evaluated. + * @return true if item matches, otherwise false. + * + * @see BaseMatcher + */ + matches(actual: Object): boolean; + + /** + * Generate a description of why the matcher has not accepted the item. + * The description will be part of a larger description of why a matching + * failed, so it should be concise. + * This method assumes that matches(item) is false, but + * will not check this. + * + * @param actual The item that the Matcher has rejected. + * @param mismatchDescription + * The description to be built or appended to. + */ + describeMismatch(actual: Object, mismatchDescription: Description): void; +} diff --git a/hamcrest/src/main/ets/components/MatcherAssert.ets b/hamcrest/src/main/ets/components/MatcherAssert.ets new file mode 100644 index 0000000000000000000000000000000000000000..774d17812acbe8de401ae1c969a8b781661eb3ca --- /dev/null +++ b/hamcrest/src/main/ets/components/MatcherAssert.ets @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from './Matcher' +import {Description} from './Description' +import {StringDescription} from './StringDescription' +import AssertionError from 'assertion-error' + +export class MatcherAssert { + public static assertThat(actual: any, matcher: Matcher): void { + MatcherAssert.assertThatWithMatcher(actual, matcher, ""); + } + + public static assertThatWithMatcher(actual: any, matcher: Matcher, reason?: String): void { + if (!matcher.matches(actual)) { + let description: Description = new StringDescription(); + description.appendText(reason) + .appendText("\n") + .appendText("Expected: ") + .appendDescriptionOf(matcher) + .appendText("\n") + .appendText(" but: "); + matcher.describeMismatch(actual, description); + + throw new AssertionError(description.toString()); + } + } + + public static assertThatWithReason(reason: String, assertion: boolean): void { + if (!assertion) { + throw new AssertionError(reason.toString()); + } + } +} diff --git a/hamcrest/src/main/ets/components/NullDescription.ets b/hamcrest/src/main/ets/components/NullDescription.ets new file mode 100644 index 0000000000000000000000000000000000000000..c4ccc4531a9d5bc6d1ef6cd89ca490c12bf68114 --- /dev/null +++ b/hamcrest/src/main/ets/components/NullDescription.ets @@ -0,0 +1,43 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from './Description'; +import { SelfDescribing } from './SelfDescribing'; + +export class NullDescription implements Description { + public appendDescriptionOf(value: SelfDescribing): Description { + return this; + } + + public appendList(start: String, separator: String, end: String, values: SelfDescribing[]): Description { + return this; + } + + public appendText(text: String): Description { + return this; + } + + public appendValue(value: Object): Description{ + return this; + } + + public appendValueList(start: String, separator: String, end: String, ... values: SelfDescribing[]): Description{ + return this; + } + + public toString(): String { + return ""; + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/SelfDescribing.ets b/hamcrest/src/main/ets/components/SelfDescribing.ets new file mode 100644 index 0000000000000000000000000000000000000000..40333fc462e0ad2ea358000717ed881e822beea9 --- /dev/null +++ b/hamcrest/src/main/ets/components/SelfDescribing.ets @@ -0,0 +1,32 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from './Description' + +/** + * The ability of an object to describe itself. + */ +export interface SelfDescribing { + + /** + * Generates a description of the object. The description may be part of a + * a description of a larger object of which this is just a component, so it + * should be worded appropriately. + * + * @param description + * The description to be built or appended to. + */ + describeTo(description: Description): void; +} diff --git a/hamcrest/src/main/ets/components/StringDescription.ets b/hamcrest/src/main/ets/components/StringDescription.ets new file mode 100644 index 0000000000000000000000000000000000000000..1e9388152e5126a730c1524217e9e6d247940ca5 --- /dev/null +++ b/hamcrest/src/main/ets/components/StringDescription.ets @@ -0,0 +1,63 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseDescription } from './BaseDescription'; +import { SelfDescribing } from './SelfDescribing'; + +/** + * A {@link Description} that is stored as a string. + */ +export class StringDescription extends BaseDescription { + value = ''; + + constructor() { + super(); + } + + /** + * Return the description of a {@link SelfDescribing} object as a String. + * + * @param selfDescribing + * The object to be described. + * @return + * The description of the object. + */ + public static convertToString(selfDescribing: SelfDescribing): String { + return new StringDescription().appendDescriptionOf(selfDescribing).toString(); + } + + /** + * Alias for {@link #toString(SelfDescribing)}. + * + * @param selfDescribing + * The object to be described. + * @return + * The description of the object. + */ + public static asString(selfDescribing: SelfDescribing): String { + return this.convertToString(selfDescribing); + } + + protected append(str: String): void { + this.value += str; + } + + /** + * Returns the description as a string. + */ + public toString(): String { + return this.value; + } +} diff --git a/hamcrest/src/main/ets/components/beans/HasProperty.ets b/hamcrest/src/main/ets/components/beans/HasProperty.ets new file mode 100644 index 0000000000000000000000000000000000000000..cb67b6c2bd4ad5ba61d4d363ad406d74cc046163 --- /dev/null +++ b/hamcrest/src/main/ets/components/beans/HasProperty.ets @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from '../Description'; +import { BaseMatcher } from '../BaseMatcher'; +import { Matcher } from '../Matcher'; + +export class HasProperty extends BaseMatcher { + private propertyName: string; + public constructor(propertyName: string) { + super(); + this.propertyName = propertyName; + } + + public matches(obj: T): boolean { + return obj == null ? false : obj.hasOwnProperty(this.propertyName) + } + + public describeMismatch(item: T, mismatchDescription: Description): void { + mismatchDescription.appendText("no ").appendValue(this.propertyName).appendText(" in ").appendValue(item); + } + + public describeTo(description: Description): void { + description.appendText("hasProperty(").appendValue(this.propertyName).appendText(")"); + } + + /** + * Creates a matcher that matches when the examined object has a JavaBean property + * with the specified name. + * For example: + *
assertThat(myBean, hasProperty("foo"))
+ * + * @param + * the matcher type. + * @param propertyName + * the name of the JavaBean property that examined beans should possess + * @return The matcher. + */ + public static hasProperty(propertyName: string): Matcher { + return new HasProperty(propertyName); + } +} diff --git a/hamcrest/src/main/ets/components/collection/ArrayMatching.ets b/hamcrest/src/main/ets/components/collection/ArrayMatching.ets new file mode 100644 index 0000000000000000000000000000000000000000..c49536287ca24861e4e6f1becfb623db83a13d6e --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/ArrayMatching.ets @@ -0,0 +1,55 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from '../Matcher' +import {HasItemInArray} from './HasItemInArray' +import {IsEqual} from '../core/IsEqual' + +export class ArrayMatching { + + /** + * Creates a matcher for arrays that matches when the examined array contains at least one item + * that is matched by the specified elementMatcher. Whilst matching, the traversal + * of the examined array will stop as soon as a matching element is found. + * For example: + *
assertThat(new String[] {"foo", "bar"}, hasItemInArray(startsWith("ba")))
+ * + * @param + * the matcher type. + * @param elementMatcher + * the matcher to apply to elements in examined arrays + * @return The matcher. + */ + public static hasItemInArrayMatcher(elementMatcher:Matcher ):Matcher { + return new HasItemInArray(elementMatcher); + } + + /** + * A shortcut to the frequently used hasItemInArray(equalTo(x)). + * For example: + *
assertThat(hasItemInArray(x))
+ * instead of: + *
assertThat(hasItemInArray(equalTo(x)))
+ * + * @param + * the matcher type. + * @param element + * the element that should be present in examined arrays + * @return The matcher. + */ + public static hasItemInArray( element:Array):Matcher> { + return this.hasItemInArrayMatcher(IsEqual.equalTo(element)); + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/collection/HasItemInArray.ets b/hamcrest/src/main/ets/components/collection/HasItemInArray.ets new file mode 100644 index 0000000000000000000000000000000000000000..c8802c2926a2a2b9fde5bd69831fe1d1391839d2 --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/HasItemInArray.ets @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from '../Matcher' +import {BaseMatcher} from '../BaseMatcher' +import {Description} from '../Description' +import {IsIterableContaining} from '../core/IsIterableContaining' + +export class HasItemInArray extends BaseMatcher> { + private readonly elementMatcher: Matcher; + private readonly collectionMatcher: BaseMatcher ; + + public constructor(elementMatcher: Matcher) { + super() + this.elementMatcher = elementMatcher; + this.collectionMatcher = new IsIterableContaining(elementMatcher); + } + + public matches(item: Object): boolean { + var source = new Array(); + source.push(item) + return this.collectionMatcher.matches(source) + } + + public describeMismatch(item: Object, mismatchDescription: Description): void { + + } + + public matchesSafely(actual: Array): boolean { + return this.collectionMatcher.matches(actual); + } + + public describeMismatchSafely(actual: Array, mismatchDescription: Description): void { + this.collectionMatcher.describeMismatch(actual, mismatchDescription); + } + + public describeTo(description: Description): void { + description + .appendText("an array containing ") + .appendDescriptionOf(this.elementMatcher); + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/collection/IsArray.ets b/hamcrest/src/main/ets/components/collection/IsArray.ets new file mode 100644 index 0000000000000000000000000000000000000000..3f2846c0eb8f058a058617a77fb5daf8accd769d --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/IsArray.ets @@ -0,0 +1,94 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {BaseMatcher} from '../BaseMatcher'; +import {Description} from '../Description' +import {Matcher} from '../Matcher' + +/** + * Matcher for array whose elements satisfy a sequence of matchers. + * The array size must equal the number of element matchers. + */ +export class IsArray extends BaseMatcher { + elementMatchers: Matcher[] + + constructor(mArray: Matcher[]) { + super(); + this.elementMatchers = mArray; + } + + describeTo(description: Description) { + description.appendList(this.descriptionStart(), this.descriptionSeparator(), this.descriptionEnd(), this.elementMatchers) + } + + matches(actual: Object) { + /** + * 类型转换 + */ + var array = []; + Object.keys(actual).forEach(function(key:string){ + array.push(actual[key]) + }) + if (array.length != this.elementMatchers.length) return false; + + for (var i = 0; i < array.length; i++) { + if (!this.elementMatchers[i].matches(array[i])) return false; + } + + return true + }; + + describeMismatch(items: Object, description: Description) { + var actual = []; + for (var key in items) { + if (!item.hasOwnProperty(key)) { + continue; + } + var item = {}; + item[key] = items[key]; + actual.push(item); + } + + if (actual.length != this.elementMatchers.length) { + + description.appendText("array length was ").appendValue(actual.length); + return; + } + + for (var i = 0; i < actual.length; i++) { + if (!this.elementMatchers[i].matches(actual[i])) { + description.appendText("element ").appendValue(i).appendText(" "); + this.elementMatchers[i].describeMismatch(actual[i], description); + return; + } + } + } + + protected descriptionStart(): string { + return "["; + } + + protected descriptionSeparator(): string { + return ", "; + } + + protected descriptionEnd(): string { + return "]"; + } + + public static array(...elementMatchers: any[]):Matcher { + return new IsArray(elementMatchers) + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/collection/IsArrayWithSize.ets b/hamcrest/src/main/ets/components/collection/IsArrayWithSize.ets new file mode 100644 index 0000000000000000000000000000000000000000..6eb2680c1d41ab68fef3a27df2c17b7842a2902f --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/IsArrayWithSize.ets @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {FeatureMatcher} from '../FeatureMatcher'; +import {Matcher} from '../Matcher' +import {IsEqual} from '../core/IsEqual' + +export class IsArrayWithSize extends FeatureMatcher, Number>{ + + public constructor(sizeMatcher:Matcher< Number> ) { + super(sizeMatcher, "an array with size","array size"); + } + + + protected featureValueOf(actual:Array):Number { + return actual.length; + } + + /** + * Creates a matcher for arrays that matches when the length of the array + * satisfies the specified matcher. + * For example: + *
assertThat(new String[]{"foo", "bar"}, arrayWithSize(equalTo(2)))
+ * @param + * the matcher type. + * @param sizeMatcher + * a matcher for the length of an examined array + * @return The matcher. + */ + public static arrayWithSize(sizeMatcher:Matcher ):Matcher> { + return new IsArrayWithSize(sizeMatcher); + } + + /** + * Creates a matcher for arrays that matches when the length of the array + * equals the specified size. + * For example: + *
assertThat(new String[]{"foo", "bar"}, arrayWithSize(2))
+ * + * @param + * the matcher type. + * @param size + * the length that an examined array must have for a positive match + * @return The matcher. + */ + public static arrayWithSizeOf(size:number):Matcher> { + return IsArrayWithSize.arrayWithSize(IsEqual.equalTo(size)); + } + +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/collection/IsIn.ets b/hamcrest/src/main/ets/components/collection/IsIn.ets new file mode 100644 index 0000000000000000000000000000000000000000..3154de8d724a2895a4b2431719dfc462f37e9e4b --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/IsIn.ets @@ -0,0 +1,44 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {BaseMatcher} from '../BaseMatcher'; +import {Description} from '../Description'; +import {Matcher} from '../Matcher' + +export class IsIn extends BaseMatcher { + collection: any[]; + + constructor(collection: any[]) { + super() + this.collection = collection + } + + matches(actual: Object) { + return this.collection.indexOf(actual) != -1 + } + + describeTo(buffer: Description) { + buffer.appendText("one of "); + buffer.appendList("{", ", ", "}", this.collection); + } + + public static isIn(collection: any[]): Matcher{ + return this.in(collection) + } + + public static in(collection: any[]): Matcher { + return new IsIn(collection); + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/collection/IsMapContaining.ets b/hamcrest/src/main/ets/components/collection/IsMapContaining.ets new file mode 100644 index 0000000000000000000000000000000000000000..aacfd9c00f4b673fbe4a974785ee148bc35700bb --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/IsMapContaining.ets @@ -0,0 +1,119 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from '../Matcher' +import {BaseMatcher} from '../BaseMatcher' +import {Description} from '../Description' +import {IsAnything} from '../core/IsAnything' +import {StringDescription} from '../StringDescription' + +export class IsMapContaining extends BaseMatcher>{ + + private readonly keyMatcher:Matcher; + private readonly valueMatcher:Matcher; + + public constructor(keyMatcher:Matcher, valueMatcher:Matcher) { + super() + this.keyMatcher = keyMatcher; + this.valueMatcher = valueMatcher; + + } + + public matchesSafely( map:Map):boolean { + map.forEach((value,key,map)=>{ + if (this.keyMatcher.matches(key) && this.valueMatcher.matches(value)) { + return true; + } + }) + return false; + } + + public describeMismatchSafely( map:Map, mismatchDescription:Description) :void{ + console.info("IsMapContaining describeMismatchSafely:"+JSON.stringify(map)) + mismatchDescription.appendText("map was ").appendValueList("[", ", ", "]", null); + } + + public describeTo( description:Description):void { + description.appendText("map containing [") + .appendDescriptionOf(this.keyMatcher) + .appendText("->") + .appendDescriptionOf(this.valueMatcher) + .appendText("]"); + } + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one entry whose key satisfies the specified keyMatcher and whose + * value satisfies the specified valueMatcher. + * For example: + *
assertThat(myMap, hasEntry(equalTo("bar"), equalTo("foo")))
+ * + * @param + * the map key type. + * @param + * the map value type. + * @param keyMatcher + * the key matcher that, in combination with the valueMatcher, must be satisfied by at least one entry + * @param valueMatcher + * the value matcher that, in combination with the keyMatcher, must be satisfied by at least one entry + * @return The matcher. + */ + public static hasEntry( keyMatcher:Matcher, valueMatcher:Matcher):Matcher> { + return new IsMapContaining(keyMatcher, valueMatcher); + } + + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one key that satisfies the specified matcher. + * For example: + *
assertThat(myMap, hasKey(equalTo("bar")))
+ * + * @param + * the map key type. + * @param keyMatcher + * the matcher that must be satisfied by at least one key + * @return The matcher. + */ + public static hasKey( keyMatcher:Matcher):Matcher> { + return new IsMapContaining(keyMatcher, IsAnything.anything()); + } + + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one value that satisfies the specified valueMatcher. + * For example: + *
assertThat(myMap, hasValue(equalTo("foo")))
+ * + * @param + * the value type. + * @param valueMatcher + * the matcher that must be satisfied by at least one value + * @return The matcher. + */ + public static hasValue(valueMatcher:Matcher):Matcher> { + return new IsMapContaining(IsAnything.anything(), valueMatcher); + } + public matches(map:Map): boolean { + map.forEach((value,key,map)=>{ + if (this.keyMatcher.matches(key) && this.valueMatcher.matches(value)) { + return true; + } + }) + return false; + } + +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/collection/IsMapWithSize.ets b/hamcrest/src/main/ets/components/collection/IsMapWithSize.ets new file mode 100644 index 0000000000000000000000000000000000000000..3ecce1647a5767aea0c39c9f7e0cb1cfcb2fe237 --- /dev/null +++ b/hamcrest/src/main/ets/components/collection/IsMapWithSize.ets @@ -0,0 +1,82 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {FeatureMatcher} from '../FeatureMatcher'; +import {Matcher} from '../Matcher' +import {IsEqual} from '../core/IsEqual' + +export class IsMapWithSize extends FeatureMatcher, Number>{ + + public constructor( sizeMatcher:Matcher) { + super(sizeMatcher, "a map with size", "map size"); + } + + + protected featureValueOf(actual:Map):Number { + return actual.size; + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the size() method returns + * a value that satisfies the specified matcher. + * For example: + *
assertThat(myMap, is(aMapWithSize(equalTo(2))))
+ * + * @param + * the map key type. + * @param + * the map value type. + * @param sizeMatcher + * a matcher for the size of an examined {@link java.util.Map} + * @return The matcher. + */ + public static aMapWithSizeOfMatcher(sizeMatcher:Matcher ):Matcher> { + return new IsMapWithSize(sizeMatcher); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the size() method returns + * a value equal to the specified size. + * For example: + *
assertThat(myMap, is(aMapWithSize(2)))
+ * + * @param + * the map key type. + * @param + * the map value type. + * @param size + * the expected size of an examined {@link java.util.Map} + * @return The matcher. + */ + public static aMapWithSize(size:number):Matcher> { + return IsMapWithSize.aMapWithSizeOfMatcher(IsEqual.equalTo(size)); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the size() method returns + * zero. + * For example: + *
assertThat(myMap, is(anEmptyMap()))
+ * + * @param + * the map key type. + * @param + * the map value type. + * @return The matcher. + */ + public static anEmptyMap():Matcher> { + return IsMapWithSize.aMapWithSizeOfMatcher(IsEqual.equalTo(0)); + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/core/AllOf.ets b/hamcrest/src/main/ets/components/core/AllOf.ets new file mode 100644 index 0000000000000000000000000000000000000000..cd6e6ead5fcdd02abba1345f27f05c20e1ec78fc --- /dev/null +++ b/hamcrest/src/main/ets/components/core/AllOf.ets @@ -0,0 +1,75 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { DiagnosingMatcher } from '../DiagnosingMatcher'; +import { Description } from '../Description'; +import { Matcher } from '../Matcher'; + +/** + * Calculates the logical conjunction of multiple matchers. Evaluation is shortcut, so + * subsequent matchers are not called if an earlier matcher returns false. + */ +export class AllOf extends DiagnosingMatcher { + private matchers: Array>; + constructor(matchers: Array>) { + super() + this.matchers = matchers; + } + + public matchesWithDiagnosingMatcher(o: Object, mismatch: Description): boolean { + for (let matcher of this.matchers) { + if (!matcher.matches(o)) { + mismatch.appendDescriptionOf(matcher).appendText(" "); + matcher.describeMismatch(o, mismatch); + return false; + } + } + return true; + } + + public describeTo(description: Description): void { + description.appendList("(", " " + "and" + " ", ")", this.matchers); + } + + /** + * Creates a matcher that matches if the examined object matches ALL of the specified matchers. + * For example: + *
assertThat("myValue", allOf(startsWith("my"), containsString("Val")))
+ * + * @param + * the matcher type. + * @param matchers + * all the matchers must pass. + * @return The matcher. + */ + public static allOf(matchers: Array>): Matcher { + return new AllOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches ALL of the specified matchers. + * For example: + *
assertThat("myValue", allOf(startsWith("my"), containsString("Val")))
+ * + * @param + * the matcher type. + * @param matchers + * all the matchers must pass. + * @return The matcher. + */ + public static allOfMatches(...matchers: Matcher[]): Matcher { + return AllOf.allOf(matchers); + } +} diff --git a/hamcrest/src/main/ets/components/core/AnyOf.ets b/hamcrest/src/main/ets/components/core/AnyOf.ets new file mode 100644 index 0000000000000000000000000000000000000000..5005178d1e4ff7f17a5821008131b50e3d3ae1c3 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/AnyOf.ets @@ -0,0 +1,67 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from '../Description'; +import { ShortcutCombination } from './ShortcutCombination'; +import { Matcher } from '../Matcher'; + + +/** + * Calculates the logical disjunction of multiple matchers. Evaluation is shortcut, so + * subsequent matchers are not called if an earlier matcher returns true. + */ +export class AnyOf extends ShortcutCombination { + public constructor(matchers: Array>) { + super(matchers); + } + + public matches(o: Object): boolean { + return super.matchesWithShortcut(o, true); + } + + public describeTo(description: Description): void { + super.describeToWithShortcut(description, "or"); + } + + /** + * Creates a matcher that matches if the examined object matches ANY of the specified matchers. + * For example: + *
assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))
+ * + * @param + * the matcher type. + * @param matchers + * any the matchers must pass. + * @return The matcher. + */ + public static anyOf(matchers: Array>): AnyOf { + return new AnyOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches ANY of the specified matchers. + * For example: + *
assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))
+ * + * @param + * the matcher type. + * @param matchers + * any the matchers must pass. + * @return The matcher. + */ + public static anyOfMatches(... matchers: Matcher[]): AnyOf { + return AnyOf.anyOf(matchers); + } +} diff --git a/hamcrest/src/main/ets/components/core/CombinableMatcher.ets b/hamcrest/src/main/ets/components/core/CombinableMatcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..be37e09d092a97c5ff8eafad9c05871005393c8f --- /dev/null +++ b/hamcrest/src/main/ets/components/core/CombinableMatcher.ets @@ -0,0 +1,56 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {DiagnosingMatcher} from '../DiagnosingMatcher'; +import {Description} from '../Description'; +import {Matcher} from '../Matcher'; +import {AllOf} from './AllOf'; +import {AnyOf} from './AnyOf'; + +export class CombinableMatcher extends DiagnosingMatcher { + private matcher: Matcher; + + public constructor(matcher: Matcher) { + super() + this.matcher = matcher; + } + + protected matchesWithDiagnosingMatcher(item: T, mismatch: Description): boolean { + if (!this.matcher.matches(item)) { + this.matcher.describeMismatch(item, mismatch); + return false; + } + return true; + } + + public describeTo(description: Description): void{ + description.appendDescriptionOf(this.matcher); + } + + public and(other: Matcher): CombinableMatcher{ + return new CombinableMatcher(new AllOf(this.templatedListWith(other))); + } + + public or(other: Matcher): CombinableMatcher { + return new CombinableMatcher(new AnyOf(this.templatedListWith(other))); + } + + private templatedListWith(other: Matcher): Array>{ + let matchers: Array> = []; + matchers.push(this.matcher); + matchers.push(other); + return matchers; + } +} diff --git a/hamcrest/src/main/ets/components/core/Every.ets b/hamcrest/src/main/ets/components/core/Every.ets new file mode 100644 index 0000000000000000000000000000000000000000..0515feb8dea7cf514cce515d9feecb1d7a4dea13 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/Every.ets @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from '../Description'; +import {Matcher} from '../Matcher'; +import {DiagnosingMatcher} from '../DiagnosingMatcher'; + +export class Every extends DiagnosingMatcher> { + private matcher: Matcher; + + public constructor(matcher: Matcher) { + super(); + this.matcher = matcher; + } + + public matchesWithDiagnosingMatcher(collection: T[], mismatchDescription: Description): boolean { + for (let t of collection) { + if (!this.matcher.matches(t)) { + mismatchDescription.appendText("an item "); + this.matcher.describeMismatch(t, mismatchDescription); + return false; + } + } + return true; + } + + public describeTo(description: Description): void { + description.appendText("every item is ").appendDescriptionOf(this.matcher); + } + + public static everyItem(itemMatcher: Matcher): Matcher> { + return new Every (itemMatcher); + } +} diff --git a/hamcrest/src/main/ets/components/core/Is.ets b/hamcrest/src/main/ets/components/core/Is.ets new file mode 100644 index 0000000000000000000000000000000000000000..cb5a9e238d6e432ba435f4bec616ad638e16fd5f --- /dev/null +++ b/hamcrest/src/main/ets/components/core/Is.ets @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {BaseMatcher} from '../BaseMatcher'; +import {Description} from '../Description'; +import {Matcher} from '../Matcher'; + +/** + * Decorates another Matcher, retaining the behaviour but allowing tests + * to be slightly more expressive. + * + * For example: assertThat(cheese, equalTo(smelly)) + * vs. assertThat(cheese, is(equalTo(smelly))) + */ +export class Is extends BaseMatcher { + + private matcher: Matcher; + + public constructor( matcher: Matcher) { + super(); + this.matcher = matcher; + } + + public matches( arg:Object):boolean { + return this.matcher.matches(arg); + } + + public describeTo( description: Description): void { + description.appendText("is ").appendDescriptionOf(this.matcher); + } + + public describeMismatch( item: Object, mismatchDescription: Description): void { + this.matcher.describeMismatch(item, mismatchDescription); + } + + /** + * Decorates another Matcher, retaining its behaviour, but allowing tests + * to be slightly more expressive. + * For example: + *
assertThat(cheese, is(equalTo(smelly)))
+ * instead of: + *
assertThat(cheese, equalTo(smelly))
+ * + * @param + * the matcher type. + * @param matcher + * the matcher to wrap. + * @return The matcher. + */ + public static is(matcher: Matcher): Matcher { + return new Is(matcher); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsAnything.ets b/hamcrest/src/main/ets/components/core/IsAnything.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ba2b04367b05ff0a19b33255ee74a8b9338d5b5 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsAnything.ets @@ -0,0 +1,52 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from '../Description'; +import { Matcher } from '../Matcher'; +import { BaseMatcher } from '../BaseMatcher'; + +/** + * A matcher that always returns true. + */ +export class IsAnything extends BaseMatcher { + private message: string; + public constructor(message?: string) { + super(); + if (message) { + this.message = message; + } + this.message = 'ANYTHING'; + } + + public matches(o: Object): boolean { + return true; + } + + public describeTo(description: Description): void{ + description.appendText(this.message); + } + + /** + * Creates a matcher that always matches, regardless of the examined object, but describes + * itself with the specified {@link String}. + * + * @param description + * a meaningful {@link String} used when describing itself + * @return The matcher. + */ + public static anything(description?: string): Matcher { + return new IsAnything(description); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsEqual.ets b/hamcrest/src/main/ets/components/core/IsEqual.ets new file mode 100644 index 0000000000000000000000000000000000000000..dfc790e7b81770a15c605b282229b28534d079e3 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsEqual.ets @@ -0,0 +1,111 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {BaseMatcher} from '../BaseMatcher'; +import {Description} from '../Description'; +import {Matcher} from '../Matcher'; + +/** + * Is the value equal to another value, as tested by the + * {@link java.lang.Object#equals} invokedMethod? + */ +export class IsEqual extends BaseMatcher { + private expectedValue: Object; + + public constructor(equalArg: T) { + super(); + this.expectedValue = equalArg; + } + + public matches(actualValue: Object): boolean{ + return IsEqual.areEqual(actualValue, this.expectedValue); + } + + public describeTo(description: Description): void { + description.appendValue(this.expectedValue); + } + + private static areEqual(actual: Object, expected: Object): boolean { + if (actual == null) { + return expected == null; + } + + if (expected != null && Array.isArray(actual)) { + return Array.isArray(expected) && IsEqual.areArraysEqual(actual, expected); + } + + return actual == expected; + } + + private static areArraysEqual(actualArray: Object, expectedArray: Object): boolean { + return IsEqual.areArrayLengthsEqual(actualArray, expectedArray) && IsEqual.areArrayElementsEqual(actualArray, expectedArray); + } + + private static areArrayLengthsEqual(actualArray: Object, expectedArray: Object): boolean { + return (> actualArray).length == (> expectedArray).length; + } + + private static areArrayElementsEqual(actualArray: Object, expectedArray: Object): boolean { + for (let i = 0; i < (> actualArray).length; i++) { + if (!IsEqual.areEqual(actualArray[i], expectedArray[i])) { + return false; + } + } + return true; + } + + /** + * Creates a matcher that matches when the examined object is logically equal to the specified + * operand, as determined by calling the {@link java.lang.Object#equals} method on + * the examined object. + * + *

If the specified operand is null then the created matcher will only match if + * the examined object's equals method returns true when passed a + * null (which would be a violation of the equals contract), unless the + * examined object itself is null, in which case the matcher will return a positive + * match.

+ * + *

The created matcher provides a special behaviour when examining Arrays, whereby + * it will match if both the operand and the examined object are arrays of the same length and + * contain items that are equal to each other (according to the above rules) in the same + * indexes.

+ * For example: + *
+     * assertThat("foo", equalTo("foo"));
+     * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"}));
+     * 
+ * + * @param + * the matcher type. + * @param operand + * the value to check. + * @return The matcher. + */ + public static equalTo(operand: Object): Matcher { + return new IsEqual (operand); + } + + /** + * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being + * compared to be of the same static type. + * + * @param operand + * the value to check. + * @return The matcher. + */ + public static equalToObject(operand: Object): Matcher { + return new IsEqual (operand); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsInstanceOf.ets b/hamcrest/src/main/ets/components/core/IsInstanceOf.ets new file mode 100644 index 0000000000000000000000000000000000000000..81fc4d44d42c7220525e66988e53833d3fb2170c --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsInstanceOf.ets @@ -0,0 +1,70 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from '../Description'; +import {DiagnosingMatcher} from '../DiagnosingMatcher'; +import {Matcher} from '../Matcher'; + +/** + * Tests whether the value is an instance of a class. + * Classes of basic types will be converted to the relevant "Object" classes + */ +export class IsInstanceOf extends DiagnosingMatcher { + + private expectedClass; + + /** + * Creates a new instance of IsInstanceOf + * + * @param expectedClass The predicate evaluates to true for instances of this class + * or one of its subclasses. + */ + public constructor(expectedClass) { + super(); + this.expectedClass = expectedClass; + } + + protected matchesWithDiagnosingMatcher(item: Object, mismatch: Description) : boolean{ + if (null == item) { + mismatch.appendText("null"); + return false; + } + + return item instanceof this.expectedClass; + } + + public describeTo( description: Description): void { + description.appendText("an instance of ").appendText(this.expectedClass.constructor.name); + } + + /** + * Creates a matcher that matches when the examined object is an instance of the specified type, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. + * + *

The created matcher assumes no relationship between specified type and the examined object.

+ * For example: + *
assertThat(new Canoe(), instanceOf(Paddlable.class));
+ * + * @param + * the matcher type. + * @param type + * the type to check. + * @return The matcher. + */ + public static instanceOf(typeValue: Object): Matcher { + return new IsInstanceOf(typeValue); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsIterableContaining.ets b/hamcrest/src/main/ets/components/core/IsIterableContaining.ets new file mode 100644 index 0000000000000000000000000000000000000000..bd0160aa0274c4ae1aa76716f6834d1c49ace599 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsIterableContaining.ets @@ -0,0 +1,142 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from '../Description'; +import {Matcher} from '../Matcher'; +import {DiagnosingMatcher} from '../DiagnosingMatcher'; +import {IsEqual} from './IsEqual'; +import {AllOf} from './AllOf'; + +export class IsIterableContaining extends DiagnosingMatcher { + private elementMatcher: Matcher; + + public constructor(elementMatcher: Matcher) { + super(); + this.elementMatcher = elementMatcher; + } + + protected matchesWithDiagnosingMatcher(collection: Array, mismatchDescription: Description): boolean { + if (this.isEmpty(collection)) { + mismatchDescription.appendText("was empty"); + return false; + } + + for (let item of collection) { + if (this.elementMatcher.matches(item)) { + return true; + } + } + + mismatchDescription.appendText("mismatches were: ["); + let isPastFirst: boolean = false; + for (let item of collection) { + if (isPastFirst) { + mismatchDescription.appendText(", "); + } + this.elementMatcher.describeMismatch(item, mismatchDescription); + isPastFirst = true; + } + mismatchDescription.appendText("]"); + return false; + } + + private isEmpty(iterable: Array): boolean { + return iterable == null ? true : iterable.length == 0; + } + + public describeTo(description: Description): void { + description + .appendText("a collection containing ") + .appendDescriptionOf(this.elementMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is matched by the specified + * itemMatcher. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + *
assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))
+ * + * @param + * the matcher type. + * @param itemMatcher + * the matcher to apply to items provided by the examined {@link Iterable} + * @return The matcher. + */ + public static hasItem(itemMatcher: Matcher): Matcher { + return new IsIterableContaining(itemMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is equal to the specified + * item. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + *
assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))
+ * + * @param + * the matcher type. + * @param item + * the item to compare against the items provided by the examined {@link Iterable} + * @return The matcher. + */ + public static hasTargetItem(item: Object): Matcher { + // Doesn't forward to hasItem() method so compiler can sort out generics. + return new IsIterableContaining(IsEqual.equalTo(item)); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is matched by the corresponding + * matcher from the specified itemMatchers. Whilst matching, each traversal of + * the examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + *
assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))
+ * + * @param + * the matcher type. + * @param itemMatchers + * the matchers to apply to items provided by the examined {@link Iterable} + * @return The matcher. + */ + public static hasItems(...itemMatchers: Matcher[]): Matcher { + return AllOf.allOf(itemMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is equal to the corresponding + * item from the specified items. Whilst matching, each traversal of the + * examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + *
assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))
+ * + * @param + * the matcher type. + * @param items + * the items to compare against the items provided by the examined {@link Iterable} + * @return The matcher. + */ + public static hasTargetItems(...items: Object[]): Matcher { + let all: Matcher[] = [] + for (let item of items) { + all.push(IsIterableContaining.hasTargetItem(item)) + } + + return AllOf.allOf(all); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsNot.ets b/hamcrest/src/main/ets/components/core/IsNot.ets new file mode 100644 index 0000000000000000000000000000000000000000..6517edef547aaf9037cbccc428588142bbdf7f1f --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsNot.ets @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseMatcher } from '../BaseMatcher'; +import { Description } from '../Description'; +import { Matcher } from '../Matcher'; + +/** + * Calculates the logical negation of a matcher. + */ +export class IsNot extends BaseMatcher { + private matcher: Matcher; + public constructor(matcher: Matcher) { + super(); + this.matcher = matcher; + } + + public matches(arg: Object): boolean { + return!this.matcher.matches(arg); + } + + public describeTo(description: Description): void { + description.appendText("not ").appendDescriptionOf(this.matcher); + } + + /** + * Creates a matcher that wraps an existing matcher, but inverts the logic by which + * it will match. + * For example: + *
assertThat(cheese, is(not(equalTo(smelly))))
+ * + * @param + * the matcher type. + * @param matcher + * the matcher whose sense should be inverted + * @return The matcher. + */ + public static not(matcher: Matcher): Matcher{ + return new IsNot(matcher); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsNull.ets b/hamcrest/src/main/ets/components/core/IsNull.ets new file mode 100644 index 0000000000000000000000000000000000000000..798863ce51fbca1c7abb82f0ffe443015edef407 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsNull.ets @@ -0,0 +1,56 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseMatcher } from '../BaseMatcher'; +import { Description } from '../Description'; +import { Matcher } from '../Matcher'; +import { IsNot } from './IsNot'; + +/** + * Is the value null? + */ +export class IsNull extends BaseMatcher { + public matches(o: Object): boolean { + return o == null; + } + + public describeTo(description: Description): void{ + description.appendText("null"); + } + + /** + * Creates a matcher that matches if examined object is null. + * For example: + *
assertThat(cheese, is(nullValue())
+ * + * @return The matcher. + */ + public static nullValue(): Matcher{ + return new IsNull(); + } + + /** + * A shortcut to the frequently used not(nullValue()). + * For example: + *
assertThat(cheese, is(notNullValue()))
+ * instead of: + *
assertThat(cheese, is(not(nullValue())))
+ * + * @return The matcher. + */ + public static notNullValue(): Matcher { + return IsNot.not(IsNull.nullValue()); + } +} diff --git a/hamcrest/src/main/ets/components/core/IsSame.ets b/hamcrest/src/main/ets/components/core/IsSame.ets new file mode 100644 index 0000000000000000000000000000000000000000..e8aa695d5b44355ab9b3152db6645052a0058467 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/IsSame.ets @@ -0,0 +1,67 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseMatcher } from '../BaseMatcher'; +import { Description } from '../Description'; +import { Matcher } from '../Matcher'; + +/** + * Is the value the same object as another value? + */ +export class IsSame extends BaseMatcher { + private object: T; + public constructor(object: T) { + super(); + this.object = object; + } + + public matches(arg: Object): boolean { + return arg === this.object; + } + + public describeTo(description: Description): void { + description.appendText("sameInstance(") + .appendValue(this.object) + .appendText(")"); + } + + /** + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param + * the matcher type. + * @param target + * the target instance against which others should be assessed + * @return The matcher. + */ + public static sameInstance(target: Object): Matcher { + return new IsSame (target); + } + + /** + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param + * the matcher type. + * @param target + * the target instance against which others should be assessed + * @return The matcher. + */ + public static theInstance(target: Object): Matcher{ + return new IsSame (target); + } +} diff --git a/hamcrest/src/main/ets/components/core/ShortcutCombination.ets b/hamcrest/src/main/ets/components/core/ShortcutCombination.ets new file mode 100644 index 0000000000000000000000000000000000000000..40bae198d7d3526aa2a44c8cf8b8b9ce046bf24b --- /dev/null +++ b/hamcrest/src/main/ets/components/core/ShortcutCombination.ets @@ -0,0 +1,44 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseMatcher } from '../BaseMatcher'; +import { Description } from '../Description'; +import { Matcher } from '../Matcher'; + +export abstract class ShortcutCombination extends BaseMatcher { + private matchers: Array>; + + public constructor(matchers: Array>) { + super(); + this.matchers = matchers; + } + + public abstract matches(o: Object): boolean; + + public abstract describeTo(description: Description): void; + + protected matchesWithShortcut(o: Object, shortcut: boolean): boolean { + for (let matcher of this.matchers) { + if (matcher.matches(o) == shortcut) { + return shortcut; + } + } + return!shortcut; + } + + public describeToWithShortcut(description: Description, operator: String): void { + description.appendList("(", " " + operator + " ", ")", this.matchers); + } +} diff --git a/hamcrest/src/main/ets/components/core/StringContains.ets b/hamcrest/src/main/ets/components/core/StringContains.ets new file mode 100644 index 0000000000000000000000000000000000000000..469402453e89385ffc4799fc64f2405fe14171a1 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/StringContains.ets @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from '../Matcher'; +import {SubstringMatcher} from './SubstringMatcher'; + +/** + * Tests if the argument is a string that contains a specific substring. + */ +export class StringContains extends SubstringMatcher { + public constructor(ignoringCase: boolean, substring: String) { + super("containing", ignoringCase, substring); + } + + protected evalSubstringOf(s: String): boolean { + return super.converted(s).indexOf(super.converted(this.substring).toString()) >= 0; + return false; + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere. + * For example: + *
assertThat("myStringOfNote", containsString("ring"))
+ * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + * @return The matcher. + */ + public static containsString(substring: String): Matcher { + return new StringContains(false, substring); + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere, ignoring case. + * For example: + *
assertThat("myStringOfNote", containsStringIgnoringCase("Ring"))
+ * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + * @return The matcher. + */ + public static containsStringIgnoringCase(substring: String): Matcher { + return new StringContains(true, substring); + } +} diff --git a/hamcrest/src/main/ets/components/core/StringEndsWith.ets b/hamcrest/src/main/ets/components/core/StringEndsWith.ets new file mode 100644 index 0000000000000000000000000000000000000000..66f3254f7508dcabec8b934cadf8bdbfdd6d509d --- /dev/null +++ b/hamcrest/src/main/ets/components/core/StringEndsWith.ets @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from '../Matcher'; +import {SubstringMatcher} from './SubstringMatcher'; + +/** + * Tests if the argument is a string that ends with a specific substring. + */ +export class StringEndsWith extends SubstringMatcher { + public constructor(ignoringCase: boolean, substring: String) { + super("ending with", ignoringCase, substring); + } + + protected evalSubstringOf(s: String): boolean { + return super.converted(s).endsWith(super.converted(this.substring).toString()); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}. + * For example: + *
assertThat("myStringOfNote", endsWith("Note"))
+ * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + * @return The matcher. + */ + public static endsWith(suffix: String): Matcher { + return new StringEndsWith(false, suffix); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}, ignoring case. + * For example: + *
assertThat("myStringOfNote", endsWithIgnoringCase("note"))
+ * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + * @return The matcher. + */ + public static endsWithIgnoringCase(suffix: String): Matcher{ + return new StringEndsWith(true, suffix); + } +} diff --git a/hamcrest/src/main/ets/components/core/StringRegularExpression.ets b/hamcrest/src/main/ets/components/core/StringRegularExpression.ets new file mode 100644 index 0000000000000000000000000000000000000000..769f5b5bf3fc6b527c92fc2df59a3b4959d8585d --- /dev/null +++ b/hamcrest/src/main/ets/components/core/StringRegularExpression.ets @@ -0,0 +1,61 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {DiagnosingMatcher} from '../DiagnosingMatcher'; +import {Description} from '../Description'; +import {Matcher} from '../Matcher'; + +export class StringRegularExpression extends DiagnosingMatcher { + private pattern: RegExp; + + protected constructor(pattern: RegExp) { + super(); + this.pattern = pattern; + } + + public describeTo(description: Description): void { + description.appendText("a string matching the pattern ").appendValue(this.pattern); + } + + protected matchesWithDiagnosingMatcher(actual: string, mismatchDescription: Description): boolean{ + if (!this.pattern.test(actual.toString())) { + mismatchDescription.appendText("the string was ").appendValue(actual); + return false; + } + return true; + } + + /** + * Creates a matcher that checks if the examined string matches a specified {@link java.util.regex.Pattern}. + * + * @param pattern + * the pattern to be used. + * @return The matcher. + */ + public static matchesRegex(pattern: RegExp): Matcher { + return new StringRegularExpression(pattern); + } + + /** + * Creates a matcher that checks if the examined string matches a specified regex. + * + * @param regex + * The regex to be used for the validation. + * @return The matcher. + */ + public static matchesStringRegex(regex: string): Matcher { + return StringRegularExpression.matchesRegex(new RegExp(regex)); + } +} diff --git a/hamcrest/src/main/ets/components/core/StringStartsWith.ets b/hamcrest/src/main/ets/components/core/StringStartsWith.ets new file mode 100644 index 0000000000000000000000000000000000000000..1fb73b2a05c0085f43580c0981c1d924ea95ef30 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/StringStartsWith.ets @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Matcher } from '../Matcher'; +import { SubstringMatcher } from './SubstringMatcher'; + +/** + * Tests if the argument is a string that starts with a specific substring. + */ +export class StringStartsWith extends SubstringMatcher { + public constructor(ignoringCase: boolean, substring: String) { + super("starting with", ignoringCase, substring) + } + + protected evalSubstringOf(s: String): boolean { + return super.converted(s).startsWith(super.converted(this.substring).toString()); + } + + /** + *

+ * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}. + *

+ * For example: + *
assertThat("myStringOfNote", startsWith("my"))
+ * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + * @return The matcher. + */ + public static startsWith(prefix: String): Matcher { + return new StringStartsWith(false, prefix); + } + + /** + *

+ * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}, ignoring case + *

+ * For example: + *
assertThat("myStringOfNote", startsWithIgnoringCase("My"))
+ * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + * @return The matcher. + */ + public static startsWithIgnoringCase(prefix: String): Matcher { + return new StringStartsWith(true, prefix); + } +} diff --git a/hamcrest/src/main/ets/components/core/SubstringMatcher.ets b/hamcrest/src/main/ets/components/core/SubstringMatcher.ets new file mode 100644 index 0000000000000000000000000000000000000000..8ce2316b7279f56ae25dc1a719a11dbbe990bcd5 --- /dev/null +++ b/hamcrest/src/main/ets/components/core/SubstringMatcher.ets @@ -0,0 +1,56 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from '../Description'; +import { BaseMatcher } from '../BaseMatcher'; + +export abstract class SubstringMatcher extends BaseMatcher { + private relationship: String; + private ignoringCase: boolean; + protected substring: String; + protected constructor(relationship: String, ignoringCase: boolean, substring: String) { + super(); + this.relationship = relationship; + this.ignoringCase = ignoringCase; + this.substring = substring; + if (null == substring) { + throw new Error("missing substring"); + } + } + + public matches(item: String): boolean { + return this.evalSubstringOf(this.ignoringCase ? item.toLowerCase() : item); + } + + public describeMismatch(item: String, mismatchDescription: Description): void { + mismatchDescription.appendText("was \"").appendText(item).appendText("\""); + } + + public describeTo(description: Description): void { + description.appendText("a string ") + .appendText(this.relationship) + .appendText(" ") + .appendValue(this.substring); + if (this.ignoringCase) { + description.appendText(" ignoring case"); + } + } + + protected converted(arg: String): String { + return this.ignoringCase ? arg.toLowerCase() : arg; + } + + protected abstract evalSubstringOf(str: String): boolean; +} diff --git a/hamcrest/src/main/ets/components/internal/ArrayIterator.ets b/hamcrest/src/main/ets/components/internal/ArrayIterator.ets new file mode 100644 index 0000000000000000000000000000000000000000..76b8392b7b28a11185441be1917f8db520dfd4f9 --- /dev/null +++ b/hamcrest/src/main/ets/components/internal/ArrayIterator.ets @@ -0,0 +1,42 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 ArrayIterator{ + private readonly array:Array; + private currentIndex:number = 0; + + public constructor( array:Array) { + if (!Array.isArray(array)) { + throw new Error("not an array"); + } + this.array = array; + } + + + public hasNext():boolean { + return this.currentIndex < this.array.length; + } + + + public next():Object { + this.currentIndex++; + return this.array.pop() + } + + public remove() :void{ + throw new Error("cannot remove items from an array"); + } + +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/internal/NullSafety.ets b/hamcrest/src/main/ets/components/internal/NullSafety.ets new file mode 100644 index 0000000000000000000000000000000000000000..fa8156de7cb12992e8c380ce9914875cda7d8bf5 --- /dev/null +++ b/hamcrest/src/main/ets/components/internal/NullSafety.ets @@ -0,0 +1,27 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {IsNull} from '../core/IsNull' +import {Matcher} from '../Matcher' + +export class NullSafety{ + public static nullSafe(itemMatchers:Matcher[]){ + var matchers:Array> = new Array>(itemMatchers.length); + itemMatchers.forEach((value:Matcher,index,array)=>{ + matchers.push(value == null ? IsNull.nullValue() : value); + }) + return matchers; +} +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/internal/SelfDescribingValue.ets b/hamcrest/src/main/ets/components/internal/SelfDescribingValue.ets new file mode 100644 index 0000000000000000000000000000000000000000..97d501c32806a8df613d7c5e320afb3ea1287c7a --- /dev/null +++ b/hamcrest/src/main/ets/components/internal/SelfDescribingValue.ets @@ -0,0 +1,31 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {SelfDescribing} from '../SelfDescribing' +import {Description} from '../Description' + +export class SelfDescribingValue implements SelfDescribing{ + + private value:object; + + public constructor( value:object) { + this.value = value; + } + + + public describeTo(description:Description):void { + description.appendValue(this.value); + } +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/internal/SelfDescribingValueIterator.ets b/hamcrest/src/main/ets/components/internal/SelfDescribingValueIterator.ets new file mode 100644 index 0000000000000000000000000000000000000000..1131496f25cb3ac26a5d868f8a003b7d1f125f46 --- /dev/null +++ b/hamcrest/src/main/ets/components/internal/SelfDescribingValueIterator.ets @@ -0,0 +1,44 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 SelfDescribingValueIterator{ + + + private readonly values:Array; + private currentIndex:number = 0; + + public constructor( array:Array) { + if (!Array.isArray(array)) { + throw new Error("not an array"); + } + this.values = array; + } + + + public hasNext():boolean { + return this.currentIndex < this.values.length; + } + + + public next():Object { + this.currentIndex++; + return this.values.pop() + } + + public remove() :void{ + throw new Error("cannot remove items from an array"); + } + +} \ No newline at end of file diff --git a/hamcrest/src/main/ets/components/number/IsCloseTo.ets b/hamcrest/src/main/ets/components/number/IsCloseTo.ets new file mode 100644 index 0000000000000000000000000000000000000000..8ff25575ab695d542c53df839cd3ce871cf749d4 --- /dev/null +++ b/hamcrest/src/main/ets/components/number/IsCloseTo.ets @@ -0,0 +1,72 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from '../Description'; +import {Matcher} from '../Matcher'; +import {BaseMatcher} from '../BaseMatcher'; + +/** + * Is the value a number equal to a value within some range of + * acceptable error? + */ +export class IsCloseTo extends BaseMatcher { + private delta: number; + private value: number; + + public constructor(value: number, error: number) { + super(); + this.delta = error; + this.value = value; + } + + public matches(item: number): boolean { + return this.actualDelta(item) <= 0.0; + } + + public describeMismatch(item: number, mismatchDescription: Description): void { + mismatchDescription.appendValue(item) + .appendText(" differed by ") + .appendValue(this.actualDelta(item)) + .appendText(" more than delta ") + .appendValue(this.delta); + } + + public describeTo(description: Description): void { + description.appendText("a numeric value within ") + .appendValue(this.delta) + .appendText(" of ") + .appendValue(this.value); + } + + private actualDelta(item: number): number { + return Math.abs(item - this.value) - this.delta; + } + + /** + * Creates a matcher of {@link Double}s that matches when an examined double is equal + * to the specified operand, within a range of +/- error. + * For example: + *
assertThat(1.03, is(closeTo(1.0, 0.03)))
+ * + * @param operand + * the expected value of matching doubles + * @param error + * the delta (+/-) within which matches will be allowed + * @return The matcher. + */ + public static closeTo(operand: number, error: number): Matcher { + return new IsCloseTo(operand, error); + } +} diff --git a/hamcrest/src/main/ets/components/number/IsNaN.ets b/hamcrest/src/main/ets/components/number/IsNaN.ets new file mode 100644 index 0000000000000000000000000000000000000000..f3177902bb13227986c5c9c9a79b29b945e279c7 --- /dev/null +++ b/hamcrest/src/main/ets/components/number/IsNaN.ets @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from '../Description'; +import {Matcher} from '../Matcher'; +import {BaseMatcher} from '../BaseMatcher'; + +/** + * Is the value a number actually not a number (NaN)? + */ +export class IsNaN extends BaseMatcher { + private constructor() { + super(); + } + + public matches(item: number): boolean { + return Number.isNaN(item); + } + + public describeMismatch(item: number, mismatchDescription: Description): void { + mismatchDescription.appendText("was ").appendValue(item); + } + + public describeTo(description: Description): void{ + description.appendText("a double value of NaN"); + } + + /** + * Creates a matcher of {@link Double}s that matches when an examined double is not a number. + * For example: + *
assertThat(Double.NaN, is(notANumber()))
+ * + * @return The matcher. + */ + public static notANumber(): Matcher { + return new IsNaN(); + } +} diff --git a/hamcrest/src/main/ets/components/number/OrderingComparison.ets b/hamcrest/src/main/ets/components/number/OrderingComparison.ets new file mode 100644 index 0000000000000000000000000000000000000000..e1cd71ea67a4b015410fe972085c541c831d8986 --- /dev/null +++ b/hamcrest/src/main/ets/components/number/OrderingComparison.ets @@ -0,0 +1,92 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Matcher} from '../Matcher'; +import {Description} from '../Description'; + +export class OrderingComparison { + private constructor() { + } + + public static comparesEqualTo(value: number): Matcher { + return { + matches(actual: number): boolean { + return value == actual; + }, + describeMismatch(actual: number, mismatchDescription: Description): void{ + super.describeMismatch(actual, mismatchDescription); + }, + describeTo(description: Description): void{ + description.appendText('equal to ').appendValue(value); + } + } + } + + public static greaterThan(value: number): Matcher{ + return { + matches(actual: number): boolean { + return actual > value; + }, + describeMismatch(actual: number, mismatchDescription: Description): void{ + super.describeMismatch(actual, mismatchDescription); + }, + describeTo(description: Description): void{ + description.appendText('greater than ').appendValue(value); + } + } + } + + public static greaterThanOrEqualTo(value: number): Matcher { + return { + matches(actual: number): boolean { + return actual >= value; + }, + describeMismatch(actual: number, mismatchDescription: Description): void{ + super.describeMismatch(actual, mismatchDescription); + }, + describeTo(description: Description): void{ + description.appendText('greater than or equal to ').appendValue(value); + } + } + } + + public static lessThan(value: number): Matcher { + return { + matches(actual: number): boolean { + return actual < value; + }, + describeMismatch(actual: number, mismatchDescription: Description): void{ + super.describeMismatch(actual, mismatchDescription); + }, + describeTo(description: Description): void{ + description.appendText('less than ').appendValue(value); + } + } + } + + public static lessThanOrEqualTo(value: number): Matcher { + return { + matches(actual: number): boolean { + return actual <= value; + }, + describeMismatch(actual: number, mismatchDescription: Description): void{ + super.describeMismatch(actual, mismatchDescription); + }, + describeTo(description: Description): void{ + description.appendText('less than or equal to ').appendValue(value); + } + } + } +} diff --git a/hamcrest/src/main/ets/components/text/CharSequenceLength.ets b/hamcrest/src/main/ets/components/text/CharSequenceLength.ets new file mode 100644 index 0000000000000000000000000000000000000000..39f4792cec4fb7e6bc2c6a007fcd6c48f5bcef6d --- /dev/null +++ b/hamcrest/src/main/ets/components/text/CharSequenceLength.ets @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {FeatureMatcher} from '../FeatureMatcher'; +import {Matcher} from '../Matcher'; +import {IsEqual} from '../core/IsEqual'; + +export class CharSequenceLength extends FeatureMatcher { + public constructor(lengthMatcher: Matcher) { + super(lengthMatcher, "a CharSequence with length", "length"); + } + + protected featureValueOf(actual: String): Number { + return actual.length; + } + + /** + * Creates a matcher of {@link CharSequence} that matches when a char sequence has the given length + * For example: + * + *
+     * assertThat("text", hasLength(4))
+     * 
+ * + * @param length the expected length of the string + * @return The matcher. + */ + public static hasLength(length: number): Matcher { + return new CharSequenceLength(IsEqual.equalTo(length)); + } + + /** + * Creates a matcher of {@link CharSequence} that matches when a char sequence has the given length + * For example: + * + *
+      * assertThat("text", hasLength(lessThan(4)))
+      * 
+ * + * @param lengthMatcher the expected length of the string + * @return The matcher. + */ + public static hasLengthMatcher(lengthMatcher: Matcher): Matcher { + return new CharSequenceLength(lengthMatcher); + } +} diff --git a/hamcrest/src/main/ets/components/text/IsBlankString.ets b/hamcrest/src/main/ets/components/text/IsBlankString.ets new file mode 100644 index 0000000000000000000000000000000000000000..0cb5dab4ea92f32ee65a162727e0bf307ee5a415 --- /dev/null +++ b/hamcrest/src/main/ets/components/text/IsBlankString.ets @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from '../Description'; +import { Matcher } from '../Matcher'; +import { BaseMatcher } from '../BaseMatcher' +import { AnyOf } from '../core/AnyOf' +import { IsNull } from '../core/IsNull' + + +/** + * Matches blank Strings (and null). + */ +export class IsBlankString extends BaseMatcher { + private static BLANK_INSTANCE: IsBlankString = new IsBlankString(); + private static NULL_OR_BLANK_INSTANCE: Matcher = AnyOf.anyOfMatches(IsNull.nullValue(), IsBlankString.BLANK_INSTANCE); + private static REGEX_WHITESPACE: RegExp = new RegExp("\\s"); + private constructor() { + super(); + } + + public matches(item: String): boolean{ + return IsBlankString.REGEX_WHITESPACE.test(item.toString()); + } + + public describeTo(description: Description): void { + description.appendText("a blank string"); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains + * zero or more whitespace characters and nothing else. + * For example: + *
assertThat("  ", is(blankString()))
+ * + * @return The matcher. + */ + public static blankString(): Matcher { + return IsBlankString.BLANK_INSTANCE; + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is null, or + * contains zero or more whitespace characters and nothing else. + * For example: + *
assertThat(((String)null), is(blankOrNullString()))
+ * + * @return The matcher. + */ + public static blankOrNullString(): Matcher{ + return IsBlankString.NULL_OR_BLANK_INSTANCE; + } +} diff --git a/hamcrest/src/main/ets/components/text/IsEmptyString.ets b/hamcrest/src/main/ets/components/text/IsEmptyString.ets new file mode 100644 index 0000000000000000000000000000000000000000..c0bb98c16cc5c6d8abe3316646a9370765f7df75 --- /dev/null +++ b/hamcrest/src/main/ets/components/text/IsEmptyString.ets @@ -0,0 +1,90 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { Description } from '../Description'; +import { Matcher } from '../Matcher'; +import { BaseMatcher } from '../BaseMatcher' +import { AnyOf } from '../core/AnyOf' +import { IsNull } from '../core/IsNull' + +/** + * Matches empty Strings (and null). + */ +export class IsEmptyString extends BaseMatcher { + private static INSTANCE: IsEmptyString = new IsEmptyString(); + private static NULL_OR_EMPTY_INSTANCE: Matcher = AnyOf.anyOfMatches(IsNull.nullValue(), IsEmptyString.INSTANCE); + private constructor() { + super() + } + + public matches(item: String): boolean { + if (item == null) { + return false + } + return item.length == 0 + } + + public describeTo(description: Description): void { + description.appendText("an empty string"); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string has zero length. + * For example: + *
assertThat("", isEmptyString())
+ * + * @deprecated use is(emptyString()) instead + * @return The matcher. + */ + public static isEmptyString(): Matcher { + return IsEmptyString.emptyString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string has zero length. + * For example: + *
assertThat("", is(emptyString()))
+ * + * @return The matcher. + */ + public static emptyString(): Matcher { + return IsEmptyString.INSTANCE; + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is null, or + * has zero length. + * For example: + *
assertThat(((String)null), isEmptyOrNullString())
+ * + * @deprecated use is(emptyOrNullString()) instead + * @return The matcher. + */ + public static isEmptyOrNullString(): Matcher { + return IsEmptyString.emptyOrNullString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is null, or + * has zero length. + * For example: + *
assertThat(((String)null), is(emptyOrNullString()))
+ * + * @return The matcher. + */ + public static emptyOrNullString(): Matcher { + return IsEmptyString.NULL_OR_EMPTY_INSTANCE; + } +} diff --git a/hamcrest/src/main/ets/components/text/IsEqualCompressingWhiteSpace.ets b/hamcrest/src/main/ets/components/text/IsEqualCompressingWhiteSpace.ets new file mode 100644 index 0000000000000000000000000000000000000000..f0331605a141ccb9c83b93de1d9236ef34ac40f9 --- /dev/null +++ b/hamcrest/src/main/ets/components/text/IsEqualCompressingWhiteSpace.ets @@ -0,0 +1,67 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {Description} from '../Description'; +import {Matcher} from '../Matcher'; +import {BaseMatcher} from '../BaseMatcher'; + +/** + * Tests if a string is equal to another string, compressing any changes in whitespace. + */ +export class IsEqualCompressingWhiteSpace extends BaseMatcher { + + private str: String; + + public constructor(str: String) { + super(); + if (str == null) { + throw new Error("Non-null value required"); + } + this.str = str; + } + + protected getString(): String { + return this.str; + } + + public matches(item: String): boolean { + console.info("matches: 1 " + ' this.str is ' + this.str + ', item is ' + item) + console.info("matches: 2 " + this.stripSpaces(this.str)) + console.info("matches: 3 " + this.stripSpaces(item)) + return this.stripSpaces(this.str) == (this.stripSpaces(item)); + } + + public describeMismatch(item: String, mismatchDescription: Description): void { + mismatchDescription.appendText("was ").appendValue(item); + } + + public describeTo(description: Description): void { + description.appendText("a string equal to ") + .appendValue(this.str) + .appendText(" compressing white space"); + } + + public stripSpaces(toBeStripped: String): String { + return toBeStripped.replace(/\s/g, "").trim(); + } + + public static equalToIgnoringWhiteSpace(expectedString: String): Matcher { + return new IsEqualCompressingWhiteSpace(expectedString); + } + + public static equalToCompressingWhiteSpace(expectedString: String): Matcher { + return new IsEqualCompressingWhiteSpace(expectedString); + } +} diff --git a/hamcrest/src/main/ets/components/text/IsEqualIgnoringCase.ets b/hamcrest/src/main/ets/components/text/IsEqualIgnoringCase.ets new file mode 100644 index 0000000000000000000000000000000000000000..e0176d543b815b10a1a71474c57ff51a1cb36043 --- /dev/null +++ b/hamcrest/src/main/ets/components/text/IsEqualIgnoringCase.ets @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 { BaseMatcher } from '../BaseMatcher' +import { Description } from '../Description' +import { Matcher } from '../Matcher' + +/** + * Tests if a string is equal to another string, regardless of the case. + */ +export class IsEqualIgnoringCase extends BaseMatcher { + private value: String; + constructor(value: String) { + super() + if (value == null) { + throw new Error("Non-null value required"); + } + this.value = value; + } + + public matches(item: String): boolean { + return this.value.toLowerCase() == item.toLowerCase(); + } + + public describeMismatch(item: String, mismatchDescription: Description): void { + super.describeMismatch(item, mismatchDescription); + } + + public describeTo(description: Description): void { + description.appendText("a string equal to ") + .appendValue(this.value) + .appendText(" ignoring case"); + } + + public static equalToIgnoringCase(expectedString: String): Matcher { + return new IsEqualIgnoringCase(expectedString); + } +} diff --git a/hamcrest/src/main/ets/components/text/MatchesPattern.ets b/hamcrest/src/main/ets/components/text/MatchesPattern.ets new file mode 100644 index 0000000000000000000000000000000000000000..c5d2542e155d5637047b0d7823a959a150714e87 --- /dev/null +++ b/hamcrest/src/main/ets/components/text/MatchesPattern.ets @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2022 Huawei Device Co., Ltd. +* Licensed under the BSD License, (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://opensource.org/licenses/BSD-3-Clause +* +* 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 {BaseMatcher} from '../BaseMatcher'; +import {Description} from '../Description'; +import {Matcher} from '../Matcher'; + +export class MatchesPattern extends BaseMatcher { + private pattern: RegExp; + + public constructor(pattern: RegExp) { + super() + this.pattern = pattern; + } + + public matches(item: string): boolean { + return this.pattern.test(item); + } + + public describeTo(description: Description): void { + description.appendText("a string matching the pattern '" + this.pattern + "'"); + } + + /** + * Creates a matcher of {@link java.lang.String} that matches when the examined string + * + * @param pattern + * the text pattern to match. + * @return The matcher. + */ + public static matchesPattern(pattern: RegExp): Matcher { + return new MatchesPattern(pattern); + } + + /** + * Creates a matcher of {@link java.lang.String} that matches when the examined string + * + * @param regex + * the regex to match. + * @return The matcher. + */ + public static matchesStringPattern(regex: string): Matcher { + return new MatchesPattern(new RegExp(regex)); + } +} diff --git a/hamcrest/src/main/resources/base/element/string.json b/hamcrest/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1e76de0c66777cfe83568615c5c2e68c61d23fed --- /dev/null +++ b/hamcrest/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/hvigorfile.js b/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..cff9f0dfcf8cb00cca34e7f50d61380cf5496868 --- /dev/null +++ b/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyAppTasks \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000000000000000000000000000000000000..2853d6f19164f17d605ea229422889c088d611f2 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "ohos_app_hamcrest", + "version": "1.0.0", + "ohos": { + "org": "huawei", + "buildTool": "hvigor", + "directoryLevel": "project" + }, + "description": "example description", + "repository": {}, + "license": "BSD License", + "dependencies": { + "hypium": "^1.0.0", + "@ohos/hvigor": "1.0.6", + "@ohos/hvigor-ohos-plugin": "1.0.6" + } +} diff --git a/screenshots/operation.png b/screenshots/operation.png new file mode 100644 index 0000000000000000000000000000000000000000..ee774330337c5dc6ccb15228c900062b9d8a0746 Binary files /dev/null and b/screenshots/operation.png differ