├── .github ├── CONTRIBUTING.md └── ISSUE_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .nvmrc ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── ke ├── docs ├── assets │ ├── css │ │ ├── main.css │ │ └── main.css.map │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ ├── main.js │ │ └── search.js ├── classes │ ├── _arbitrary_.arbitrary.html │ ├── _definition_.definitions.html │ ├── _property_.forall.html │ └── _traits_.chainable.html ├── globals.html ├── index.html ├── interfaces │ ├── _arbitrary_.arbitraryattributes.html │ ├── _arbitrary_.arbitraryoptions.html │ ├── _constants_.checkoptions.html │ ├── _property_.checkresult.html │ ├── _property_.testresult.html │ ├── _types_graphic_image_.lorempixurlopts.html │ ├── _types_primitive_number_.hexstringgenopts.html │ └── _types_primitive_number_.numbergenopts.html └── modules │ ├── _arbitrary_.html │ ├── _combinators_collections_.html │ ├── _combinators_eval_.html │ ├── _combinators_func_.html │ ├── _combinators_index_.html │ ├── _combinators_pickers_.html │ ├── _combinators_value_.html │ ├── _constants_.html │ ├── _definition_.html │ ├── _gen_.html │ ├── _index_.html │ ├── _integrations_index_.html │ ├── _integrations_mocha_.html │ ├── _property_.html │ ├── _seq_.html │ ├── _shrink_.html │ ├── _traits_.html │ ├── _types_graphic_color_.html │ ├── _types_graphic_image_.html │ ├── _types_graphic_index_.html │ ├── _types_index_.html │ ├── _types_internet_definitions_en_avataruri_.html │ ├── _types_internet_definitions_en_index_.html │ ├── _types_internet_definitions_index_.html │ ├── _types_internet_index_.html │ ├── _types_literate_definitions_en_index_.html │ ├── _types_literate_definitions_index_.html │ ├── _types_literate_index_.html │ ├── _types_locale_avaliablelocaleids_.html │ ├── _types_locale_country_.html │ ├── _types_locale_index_.html │ ├── _types_locale_timezone_.html │ ├── _types_location_definitions_en_address_.html │ ├── _types_location_definitions_en_buildingnumber_.html │ ├── _types_location_definitions_en_city_.html │ ├── _types_location_definitions_en_cityprefix_.html │ ├── _types_location_definitions_en_citysuffix_.html │ ├── _types_location_definitions_en_county_.html │ ├── _types_location_definitions_en_index_.html │ ├── _types_location_definitions_en_postcode_.html │ ├── _types_location_definitions_en_secondaryaddress_.html │ ├── _types_location_definitions_en_state_.html │ ├── _types_location_definitions_en_stateabbr_.html │ ├── _types_location_definitions_en_street_.html │ ├── _types_location_definitions_en_streetaddress_.html │ ├── _types_location_definitions_en_streetsuffix_.html │ ├── _types_location_definitions_index_.html │ ├── _types_location_definitions_zh_hant_tw_address_.html │ ├── _types_location_definitions_zh_hant_tw_buildingnumber_.html │ ├── _types_location_definitions_zh_hant_tw_city_.html │ ├── _types_location_definitions_zh_hant_tw_cityprefix_.html │ ├── _types_location_definitions_zh_hant_tw_citysuffix_.html │ ├── _types_location_definitions_zh_hant_tw_county_.html │ ├── _types_location_definitions_zh_hant_tw_index_.html │ ├── _types_location_definitions_zh_hant_tw_postcode_.html │ ├── _types_location_definitions_zh_hant_tw_secondaryaddress_.html │ ├── _types_location_definitions_zh_hant_tw_state_.html │ ├── _types_location_definitions_zh_hant_tw_stateabbr_.html │ ├── _types_location_definitions_zh_hant_tw_street_.html │ ├── _types_location_definitions_zh_hant_tw_streetaddress_.html │ ├── _types_location_definitions_zh_hant_tw_streetsuffix_.html │ ├── _types_location_index_.html │ ├── _types_person_definitions_en_firstname_.html │ ├── _types_person_definitions_en_gender_.html │ ├── _types_person_definitions_en_index_.html │ ├── _types_person_definitions_en_lastname_.html │ ├── _types_person_definitions_en_name_.html │ ├── _types_person_definitions_index_.html │ ├── _types_person_definitions_zh_hant_tw_firstname_.html │ ├── _types_person_definitions_zh_hant_tw_gender_.html │ ├── _types_person_definitions_zh_hant_tw_index_.html │ ├── _types_person_definitions_zh_hant_tw_lastname_.html │ ├── _types_person_definitions_zh_hant_tw_name_.html │ ├── _types_person_index_.html │ ├── _types_primitive_any_.html │ ├── _types_primitive_boolean_.html │ ├── _types_primitive_datetime_.html │ ├── _types_primitive_falsy_.html │ ├── _types_primitive_index_.html │ ├── _types_primitive_number_.html │ ├── _types_primitive_string_.html │ └── _utils_.html ├── mocha.opts ├── package.json ├── src ├── arbitrary.test.ts ├── arbitrary.ts ├── combinators │ ├── collections.test.ts │ ├── collections.ts │ ├── eval.test.ts │ ├── eval.ts │ ├── func.test.ts │ ├── func.ts │ ├── index.ts │ ├── picker.test.ts │ ├── pickers.ts │ └── value.ts ├── constants.ts ├── definition.test.ts ├── definition.ts ├── gen.ts ├── idnex.d.ts ├── index.ts ├── integrations │ ├── index.ts │ ├── mocha.test.ts │ └── mocha.ts ├── property.test.ts ├── property.ts ├── seq.ts ├── shrink.test.ts ├── shrink.ts ├── traits.ts ├── types │ ├── graphic │ │ ├── color.ts │ │ ├── image.ts │ │ └── index.ts │ ├── index.ts │ ├── internet │ │ ├── definitions │ │ │ ├── en │ │ │ │ ├── avatarURI.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── index.ts │ ├── literate │ │ ├── definitions │ │ │ ├── en │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── index.ts │ ├── locale │ │ ├── avaliableLocaleids.ts │ │ ├── country.ts │ │ ├── index.ts │ │ └── timeZone.ts │ ├── location │ │ ├── definitions │ │ │ ├── en │ │ │ │ ├── address.ts │ │ │ │ ├── buildingNumber.ts │ │ │ │ ├── city.ts │ │ │ │ ├── cityPrefix.ts │ │ │ │ ├── citySuffix.ts │ │ │ │ ├── county.ts │ │ │ │ ├── index.ts │ │ │ │ ├── postcode.ts │ │ │ │ ├── secondaryAddress.ts │ │ │ │ ├── state.ts │ │ │ │ ├── stateAbbr.ts │ │ │ │ ├── street.ts │ │ │ │ ├── streetAddress.ts │ │ │ │ └── streetSuffix.ts │ │ │ ├── index.ts │ │ │ └── zh-Hant-TW │ │ │ │ ├── address.ts │ │ │ │ ├── buildingNumber.ts │ │ │ │ ├── city.ts │ │ │ │ ├── cityPrefix.ts │ │ │ │ ├── citySuffix.ts │ │ │ │ ├── county.ts │ │ │ │ ├── index.ts │ │ │ │ ├── postcode.ts │ │ │ │ ├── secondaryAddress.ts │ │ │ │ ├── state.ts │ │ │ │ ├── stateAbbr.ts │ │ │ │ ├── street.ts │ │ │ │ ├── streetAddress.ts │ │ │ │ └── streetSuffix.ts │ │ └── index.ts │ ├── person │ │ ├── definitions │ │ │ ├── en │ │ │ │ ├── firstName.ts │ │ │ │ ├── gender.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lastName.ts │ │ │ │ └── name.ts │ │ │ ├── index.ts │ │ │ └── zh-Hant-TW │ │ │ │ ├── firstName.ts │ │ │ │ ├── gender.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lastName.ts │ │ │ │ └── name.ts │ │ └── index.ts │ └── primitive │ │ ├── any.test.ts │ │ ├── any.ts │ │ ├── boolean.test.ts │ │ ├── boolean.ts │ │ ├── datetime.test.ts │ │ ├── datetime.ts │ │ ├── falsy.test.ts │ │ ├── falsy.ts │ │ ├── index.ts │ │ ├── number.test.ts │ │ ├── number.ts │ │ └── string.ts └── utils.ts ├── tsconfig.json └── yarn.lock /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Kuansim 2 | 3 | ### Issue and Pull Request Labels 4 | 5 | | Label name | Description | 6 | | --- | --- | 7 | | `enhancement` | Feature requests. | 8 | | `bug` | Confirmed bugs or reports that are very likely to be bugs. | 9 | | `question` | Questions more than bug reports or feature requests (e.g. how do I do X). | 10 | | `research` | Study tasks. | 11 | | `duplicate` | Issues which are duplicates of other issues, i.e. they have been reported before. | 12 | | `wontfix` | We decided not to fix these issues for now, either because they're working as intended or for some other reason. | 13 | | `invalid` | Issues which aren't valid (e.g. user errors). | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Detailed Description 4 | 5 | 6 | ## Context 7 | 8 | 9 | 10 | ## Possible Implementation 11 | 12 | 13 | ## References (optional) 14 | 15 | - [link](link) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | node_modules/* 3 | *.swp 4 | *.swo 5 | *~ 6 | lib 7 | .nyc_output/* 8 | dist 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | tools 4 | example 5 | webpack.config.js 6 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 7.10.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | cache: yarn 4 | 5 | node_js: 6 | - "7" 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Chen Hsin-Yi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/hychen/ke-e.svg?branch=master)](https://travis-ci.org/hychen/ke-e) 2 | [![License](http://img.shields.io/:license-mit-blue.svg)](http://badges.mit-license.org/) 3 | 4 | # ké--ê 5 | 6 | `ké--ê` is a property-based testing library, inspired by [QuickCheck](https://hackage.haskell.org/package/QuickCheck), 7 | [Hypothesis](https://github.com/HypothesisWorks/hypothesis-python), [JSVerify](https://github.com/jsverify/jsverify) and 8 | [faker.js](https://github.com/marak/Faker.js/). 9 | 10 | It is also available to generate fake data for many purpose like faker.js. 11 | 12 | ## What is ké--ê? 13 | 14 | 假的 (ké--ê) is a Taiwanese word. the meaning is fake things in English. 15 | 16 | ## Features 17 | 18 | - Property-based test utilities library. 19 | - Repeatable random fake data generators. 20 | - Mocha test framwork integration. 21 | - Support for multiple localities. 22 | - Support for browser and Node.js. 23 | 24 | check [documents](http://hychen.me/ke-e/index.html) for more details. 25 | 26 | ### Property-Based Testing 27 | 28 | Property-based tests make statements about the output of your code based on the input, and these statements 29 | are verified for many different possible inputs. 30 | 31 | By default, `ke.hold` runs 50 tests. it reports a counter example does not satisfy the property 32 | if any test fail. 33 | 34 | for example, the following test. 35 | 36 | ``` 37 | describe('Int', () => { 38 | ke.hold( 39 | '> 0', // property name. 40 | x => x > 0 // predicate. 41 | ) 42 | .over(0) // first especially case. 43 | .over(2) // second especially case. 44 | .over(ke.int) // universal case. 45 | }) 46 | ``` 47 | 48 | will report: 49 | 50 | ``` 51 | 1) Int > 0: 52 | 53 | AssertionError: > 0 doesn't hold, counter example: -5, tried: 1/100 54 | + expected - actual 55 | 56 | -false 57 | +true 58 | ``` 59 | 60 | ### Exception-Based Testing 61 | 62 | You can still use `chai` to do the testing with random test values 63 | generated by `ke-e`. 64 | 65 | ``` 66 | describe('Nat', () => { 67 | it('>= 0', () => { 68 | ke.forall(ke.nat).eval((n) => { 69 | expect(n >= 0).eq(true); 70 | }); 71 | } 72 | }) 73 | ``` 74 | 75 | ### Repeatable 76 | 77 | test results are repeatable. 78 | 79 | ``` 80 | $ mocha 81 | 1) Int >0: 82 | AssertionError: >0 doesn't hold, seed: -1764850555, counter example: -5265798245849472, tried: 3/3` 83 | 84 | ``` 85 | 86 | ``` 87 | Seed=-1764850555 mocha 88 | 1) Int >0: 89 | AssertionError: >0 doesn't hold, seed: -1764850555, counter example: -5265798245849472, tried: 3/3` 90 | ``` 91 | 92 | ### Localization 93 | 94 | This project follows unicode CLDR specification. `en` is default locale id. 95 | 96 | ``` 97 | // Generate English first name. 98 | ke.person.firstName.random. 99 | 100 | // Generate Transitional Chinese first name. 101 | ke.person.firstName.locale('zh-Hant-TW').random. 102 | ``` 103 | 104 | ### Node.js REPL 105 | 106 | ``` 107 | $ ke 108 | > ke.int.random 109 | 123124343 110 | ``` 111 | 112 | ## Arbitraries 113 | 114 | The purpose of a arbitraries is random generation and shrinking of values 115 | in property-based testing, but you could use them to generate fake data 116 | individually. 117 | 118 | some of definitions of arbitraries took from 119 | [faker.js](https://github.com/marak/Faker.js/) project. 120 | 121 | ### Primitive 122 | 123 | - any - produce any primitive types. 124 | - boolean — produce true and false with equal probability. 125 | - falsy — produce falsy values: false, null, undefined, '', 0, and NaN. 126 | - nat — produce a natural number. 127 | - int — produce a integer. 128 | - pint — produce a positive integer. 129 | - nint — produce a negative integer. 130 | - num — produce a float numbers. 131 | - pnum — produce a positive float numbers. 132 | - nnum — produce negative float numbers. 133 | - char — produce a unicode character. 134 | - asciichar — produce an ascii character. 135 | - string — produce a unicode string. 136 | - nestring - produce a non-empty unicode string. 137 | - asciistring — produce an ascii string. 138 | - neasciistring — produce an non-empty ascii string. 139 | 140 | ### Combinator 141 | 142 | - constant — produce a constant value. 143 | - elements — produce one of the given values. 144 | - regex - produce a value from the regular expression. 145 | - frequency - Choose one of the given arbitraries, with a weighted random distribution. 146 | - oneOf — randomly uses one of the given generators. 147 | - maybe - produce a value or null. 148 | - array — produce an array. 149 | - nearray — produce a non-empty array. 150 | - sequence — produce an array of given arbitraries in order. 151 | - object — produce an object. 152 | - impl - produce a instance of class C. 153 | - call - produces a value of function with given arbitrary arguments. 154 | - func — produce a function. 155 | - genfunc - produce a generator. 156 | - promise - produce a promise. 157 | - recursive - produce a recursive value. 158 | 159 | ### Locale 160 | 161 | - locale 162 | - localeids — produce a locale id. 163 | - country 164 | - timezone 165 | 166 | ### Datetime 167 | 168 | - date — produce a Date. 169 | 170 | ### Literate 171 | - literate 172 | - word 173 | - words 174 | - sentence 175 | - sentences 176 | - paragraph 177 | - paragraphs 178 | - lines 179 | - text 180 | 181 | ### Person 182 | 183 | - person - produce an object to reprsent a person. 184 | - name - produce the name of a person. 185 | - firstName - produce the first name of a person. 186 | - lastName - produce the last name of a person. 187 | - gender - produce the gender of a person. 188 | 189 | ### Internet 190 | 191 | - internet 192 | - avatar - produce an avatar uri. 193 | - userName - produce a internet username. 194 | - password - produce a password string. 195 | - email - produce an email. 196 | - url - produce an url. 197 | 198 | ### Location 199 | 200 | - location 201 | - address 202 | - streetAddress 203 | - state 204 | - abbr 205 | - zipCode 206 | - county 207 | - city 208 | - street 209 | - buildingNumber 210 | - latitude - produce an latitude. 211 | - longitude - produce an longitude. 212 | - coordinates - produce a coordinates. 213 | 214 | ### Grahpic 215 | 216 | - graphic 217 | - color 218 | - rgba 219 | - hsla 220 | - hsva 221 | - hex 222 | - hexCode 223 | - image 224 | - imageURL - an image url. 225 | - grayImageURL - a gray image url. 226 | 227 | ## Installation 228 | 229 | ### Node.js 230 | 231 | install the module with: npm install ke-e 232 | 233 | ```javascript 234 | import ke from `ke-e` 235 | 236 | describe('Integer', () => { 237 | ke.hold( 238 | 'x + y = y + x' 239 | (x, y) => x + y === y + x 240 | ).over(ke.int, ke.int); 241 | }); 242 | ``` 243 | 244 | ### Browser using script tag 245 | 246 | Download ke-e.js and place it in your project, then add it as the follwoing. 247 | 248 | dones not work now. 249 | 250 | ```html 251 | 260 | ``` 261 | 262 | ## Get Involved 263 | 264 | - source code : [github.com/hychen/ke-e](https://github.com/hychen/ke-e). 265 | 266 | ## License 267 | 268 | The MIT License (MIT) 269 | 270 | -------------------------------------------------------------------------------- /bin/ke: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('ts-babel-node/register') 3 | require('babel-polyfill') 4 | var ke = require('../src/index'); 5 | var repl = require('repl'); 6 | var r = repl.start('> '); 7 | r.context.ke = ke.default; -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hychen/ke-e/2a632975014f92b8def0a2caf4020fb2332e8ddf/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hychen/ke-e/2a632975014f92b8def0a2caf4020fb2332e8ddf/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hychen/ke-e/2a632975014f92b8def0a2caf4020fb2332e8ddf/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hychen/ke-e/2a632975014f92b8def0a2caf4020fb2332e8ddf/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /docs/modules/_combinators_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "combinators/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "combinators/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_internet_definitions_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/internet/definitions/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/internet/definitions/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_literate_definitions_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/literate/definitions/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/literate/definitions/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_locale_country_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/locale/country" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/locale/country"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_locale_timezone_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/locale/timeZone" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/locale/timeZone"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_location_definitions_en_city_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/location/definitions/en/city" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/location/definitions/en/city"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_location_definitions_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/location/definitions/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/location/definitions/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_person_definitions_en_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/person/definitions/en/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/person/definitions/en/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_person_definitions_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/person/definitions/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/person/definitions/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/modules/_types_primitive_index_.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | "types/primitive/index" | ke-e 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

External module "types/primitive/index"

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 86 |
87 |
88 | 147 |
148 |

Generated using TypeDoc

149 |
150 |
151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /mocha.opts: -------------------------------------------------------------------------------- 1 | --compilers js:ts-babel-node/register 2 | --reporter list 3 | --require babel-polyfill 4 | --recursive 5 | --colors 6 | --timeout 5000 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ke-e", 3 | "version": "0.7.1", 4 | "description": "a property-based testing framwork.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git://github.com/hychen/ke-e.git" 8 | }, 9 | "types": "src/index.d.ts", 10 | "directories": { 11 | "lib": "./lib" 12 | }, 13 | "homepage": "http:/hychen.me/ke-e/ke-e.js", 14 | "main": "lib/index.js", 15 | "bugs": { 16 | "url": "https://github.com/hychen/ke-e/issues" 17 | }, 18 | "engines": { 19 | "node": ">=7" 20 | }, 21 | "keywords": [ 22 | "test", 23 | "quickcheck" 24 | ], 25 | "author": "Chen Hsin-Yi", 26 | "license": "MIT", 27 | "scripts": { 28 | "build": "yarn run build:nodejs", 29 | "build:nodejs": "./node_modules/.bin/tsc", 30 | "test": "yarn unit", 31 | "unit": "./node_modules/.bin/mocha --opts mocha.opts $(find src -name *.test.ts)", 32 | "docs": "yarn docs:html && open docs/index.html", 33 | "docs:html": "./node_modules/.bin/typedoc --tsconfig tsconfig.json -out docs", 34 | "changelog": "./node_modules/bin/standard-version" 35 | }, 36 | "dependencies": { 37 | "@types/chai": "^3.5.2", 38 | "@types/mocha": "^2.2.41", 39 | "@types/random-js": "^1.0.28", 40 | "chai": "^3.5.0", 41 | "random-js": "^1.0.8" 42 | }, 43 | "devDependencies": { 44 | "babel-polyfill": "^6.23.0", 45 | "mocha": "^3.4.1", 46 | "pre-commit": "^1.2.2", 47 | "randexp": "^0.4.5", 48 | "repl": "^0.1.3", 49 | "ts-babel-node": "^1.1.1", 50 | "ts-node": "^3.0.4", 51 | "typedoc": "^0.7.0", 52 | "typescript": "^2.3.2" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/arbitrary.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { integer, Engine } from 'random-js'; 3 | import { Arbitrary } from '../src/arbitrary'; 4 | 5 | describe('Arbitrary', () => { 6 | describe('#constructor()', () => { 7 | it('default locale is en', () => { 8 | const arb = new Arbitrary({ 9 | gen: () => (engine) => integer(0, 2)(engine) 10 | }); 11 | expect(arb.get('locale')).eq('en'); 12 | }); 13 | }); 14 | describe('#attr()', () => { 15 | it('changes the value of a attribute', () => { 16 | const arb = new Arbitrary({ 17 | gen: () => (engine) => integer(0, 2)(engine) 18 | }); 19 | expect(arb.set('name', 'hi').get('name')).eq('hi'); 20 | }); 21 | }); 22 | describe('#choose()', () => { 23 | it('creates a new arbitrary with different generator range', () => { 24 | const arb = new Arbitrary({ 25 | gen: (opts: { min: number }) => (engine) => integer(opts.min, 2)(engine), 26 | }); 27 | const arb2 = arb.choose({ min: 1 }); 28 | expect(arb2).to.not.eql(arb); 29 | expect(arb2.genOpts).eql({ min: 1 }); 30 | }) 31 | }); 32 | describe('#suchThat', () => { 33 | const arb = new Arbitrary({ 34 | gen: () => (engine) => integer(0, 2)(engine) 35 | }); 36 | const arb2 = arb.suchThat(n => n == 2); 37 | expect(arb2.random).eq(2); 38 | }); 39 | describe('#transform()', () => { 40 | it('transforms a arbitrary A to arbitrary B.', () => { 41 | const arb = new Arbitrary({ 42 | gen: () => engine => integer(1, 2)(engine), 43 | genOpts: { min: 1 } 44 | }); 45 | const arb2 = arb.transform((n: number) => n + 'a'); 46 | expect(arb2.random.indexOf('a')).gt(-1); 47 | }) 48 | }); 49 | describe('#random', () => { 50 | it('returns a value with type T', () => { 51 | const arb = new Arbitrary({ 52 | gen: () => (engine) => integer(0, 2)(engine) 53 | }); 54 | expect(0 <= arb.random && arb.random <= 2).eq(true); 55 | }); 56 | }); 57 | }); -------------------------------------------------------------------------------- /src/arbitrary.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Random generation and shrinking of values. 3 | */ 4 | import { cloneDeep, get, defaults } from 'lodash'; 5 | import { Engine, uuid4 } from 'random-js'; 6 | import { stdOpts } from './constants'; 7 | import { Chainable } from './traits'; 8 | import * as seq from './seq'; 9 | import { 10 | Gen, 11 | Generator, 12 | GenOptsTransform, 13 | GenTransform, 14 | ValueTransform, 15 | ValuePredication, 16 | promote, 17 | suchThat 18 | } from './gen'; 19 | import { 20 | Shrinker, 21 | shrinkNoop 22 | } from './shrink'; 23 | 24 | export type Sampler = (count: number) => V[]; 25 | 26 | /** 27 | * Options of an Arbitrary. 28 | */ 29 | export interface ArbitraryOptions { 30 | attrs?: { 31 | engine?: Engine; 32 | name?: string; 33 | locale?: string; 34 | } 35 | gen: Gen; 36 | genOpts?: GenOptsT; 37 | shrinker?: Shrinker; 38 | smaller?: GenOptsTransform | null; 39 | } 40 | 41 | /** 42 | * Attributes of an Arbitrary. 43 | */ 44 | export interface ArbitraryAttributes { 45 | engine: Engine; 46 | name: string; 47 | locale: string; 48 | definition: (v: any) => boolean; 49 | } 50 | 51 | /** 52 | * Random generation and shrinking of values. 53 | * 54 | * Type Variable: 55 | * - V : The type of produced value of this arbitrary. 56 | * - O : The type of options of Gen of this arbitrary. 57 | * - TV : The type of transformed value. 58 | * - TO : The type of transformed options. 59 | */ 60 | export class Arbitrary extends Chainable { 61 | readonly gen: Gen; 62 | readonly genOpts: O | null; 63 | readonly shrinker: Shrinker; 64 | readonly smaller: GenOptsTransform | null; 65 | /** 66 | * Create an Arbitrary 67 | */ 68 | constructor(opts: ArbitraryOptions) { 69 | super(); 70 | /** 71 | * Put all attributes need to be protected in `attrs`. 72 | */ 73 | this.attrs = defaults(opts.attrs, { 74 | engine: stdOpts.engine, 75 | name: uuid4(get(opts, 'attrs.engine') || stdOpts.engine), 76 | locale: stdOpts.locale, 77 | definition: () => true 78 | }); 79 | /** 80 | * The following attributes are immutable and can only be changed via 81 | * transform methods that always returns a new arbitrary. 82 | */ 83 | this.gen = opts.gen.bind(this); 84 | this.genOpts = opts.genOpts || null; 85 | this.shrinker = opts.shrinker || shrinkNoop; 86 | this.smaller = opts.smaller || null; 87 | } 88 | /** 89 | * Clone this arbitrary. 90 | */ 91 | clone() { 92 | return cloneDeep(this); 93 | } 94 | /** 95 | * Create an Arbitrary with new locale. 96 | */ 97 | locale(locale: string) { 98 | return this.clone().set('locale', locale); 99 | } 100 | get random() { 101 | return this.generate(); 102 | } 103 | /** 104 | * Run a Generator to produce a value. 105 | */ 106 | generate(): V { 107 | return this.makeGenerator()(this.attrs.engine, this.attrs.locale); 108 | } 109 | /** 110 | * Make a Generator. 111 | */ 112 | makeGenerator(): Generator { 113 | if (this.genOpts) { 114 | return this.gen(this.genOpts); 115 | } else { 116 | return this.gen(); 117 | } 118 | } 119 | /** 120 | * Create a sampler for a given arbitrary with an optional size. 121 | */ 122 | makeSampler(): Sampler { 123 | return (count = 10) => { 124 | const acc = []; 125 | for (let i = 0; i < count; i++) { 126 | acc.push(this.random); 127 | } 128 | return acc; 129 | } 130 | } 131 | /** 132 | * Create an arbitrary with smaller range. 133 | */ 134 | get small() { 135 | return this.smaller ? this.transformWith(null, this.smaller, null) : this; 136 | } 137 | /** 138 | * Create a new arbitrary with new 139 | * inclusive range of its generator maker. 140 | */ 141 | choose(genOpts: Partial): Arbitrary { 142 | return this.transformWith(null, (oriGenOpts) => defaults(genOpts, oriGenOpts), null); 143 | } 144 | /** 145 | * Generates a value that satisfies a predicate. 146 | */ 147 | suchThat(predicate: ValuePredication): Arbitrary { 148 | return this.transformWith(suchThat(predicate), null, null); 149 | } 150 | /** 151 | * Transform Arbitrary A to Arbitrary B with value transform only. 152 | * @param f A function to transform produced value. 153 | */ 154 | transform(f: ValueTransform): Arbitrary { 155 | return this.transformWith(promote(f), null, null); 156 | } 157 | /** 158 | * Transform Arbitrary A to Arbitrary B. 159 | * @param f A function to transform produced value. 160 | * @param g A function to transform options of Gen. 161 | * @param s A function transform shrinker. 162 | */ 163 | transformWith( 164 | f: GenTransform | null, 165 | g: GenOptsTransform | null, 166 | s: Function | null 167 | ): Arbitrary { 168 | return new Arbitrary({ 169 | attrs: cloneDeep(this.attrs), 170 | gen: f ? f(this.gen) : this.gen, 171 | genOpts: g ? g(this.genOpts) : this.genOpts, 172 | shrinker: s ? s(this.shrinker) : s, 173 | smaller: this.smaller 174 | }); 175 | } 176 | /** 177 | * Shrinks the value. 178 | */ 179 | shrink(v: V): seq.Seq { 180 | return seq.filter(this.attrs.definition, this.shrinker(v)); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/combinators/collections.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { 3 | array 4 | } from './collections'; 5 | 6 | describe('Collection Combinator', () => { 7 | describe('Array', () => { 8 | it('produces', () => { 9 | const x = array().small.random; 10 | expect(Array.isArray(x)).eq(true); 11 | }); 12 | }); 13 | }); -------------------------------------------------------------------------------- /src/combinators/collections.ts: -------------------------------------------------------------------------------- 1 | import { integer} from 'random-js'; 2 | import { Arbitrary } from '../arbitrary'; 3 | import { ulog2 } from '../utils'; 4 | import { any } from '../types/primitive/any'; 5 | 6 | export type RecursiveGenOpts = { 7 | combinator: Function, 8 | arb: Arbitrary 9 | depth: number 10 | } 11 | 12 | /** 13 | * Produce a nested values. 14 | */ 15 | export function recursive( 16 | combinator: Function, 17 | arb: Arbitrary, 18 | depth: number 19 | ) { 20 | return new Arbitrary({ 21 | gen: function ({ combinator, arb, depth }: RecursiveGenOpts) { 22 | return function (engine, locale) { 23 | function rec(n: number): Arbitrary> { 24 | const chance = integer(0, 3)(engine); 25 | if (n <= 0 || chance === 0) { 26 | return n === depth ? combinator(arb) : arb; 27 | } 28 | else { 29 | return combinator(rec(n - 1)); 30 | } 31 | }; 32 | return rec(depth).makeGenerator()(engine, locale); 33 | }; 34 | }, 35 | genOpts: { combinator: combinator, arb: arb, depth: 4 } 36 | }).set('name', 'Recursive'); 37 | } 38 | 39 | /** 40 | * Options of ArrayGen 41 | */ 42 | export type ArrayGenOpts = { 43 | min: number, 44 | max: number 45 | }; 46 | 47 | /** 48 | * Generates an array of random length. 49 | */ 50 | export function array(arb?: Arbitrary): Arbitrary { 51 | return new Arbitrary({ 52 | gen: function ({ min, max }: ArrayGenOpts) { 53 | return function (engine, locale) { 54 | const n = integer(min, max)(engine); 55 | return [...new Array(n).keys()].map(() => { 56 | const chosenArb = arb ? arb : recursive(array, any, 2); 57 | return chosenArb.makeGenerator()(engine, locale); 58 | }); 59 | }; 60 | }, 61 | genOpts: { min: 0, max: 30 }, 62 | smaller: function (opts: ArrayGenOpts): ArrayGenOpts { 63 | return { min: ulog2(opts.min), max: ulog2(opts.max) }; 64 | } 65 | }).set('name', 'Array'); 66 | } 67 | 68 | /** 69 | * 70 | * Generates an non-empty array. 71 | */ 72 | export function nearray(arb: Arbitrary) { 73 | return array(arb).choose({ min: 1 }).set('name', 'Non-Empty Array'); 74 | }; 75 | 76 | /** 77 | * Generate a ordered array. 78 | */ 79 | export function sequence(...arbs: any[]) { 80 | return new Arbitrary({ 81 | gen: function (pool: any[]) { 82 | return function (engine, locale) { 83 | return pool.map(arb => { 84 | return arb instanceof Arbitrary 85 | ? arb.makeGenerator()(engine, locale) 86 | : arb; 87 | }); 88 | } 89 | } 90 | , 91 | genOpts: arbs, 92 | }).set('name', 'Sequence'); 93 | } 94 | 95 | /** 96 | * Produces an object. 97 | */ 98 | export function object(spec: { [key: string]: any }) { 99 | return new Arbitrary({ 100 | gen: function (opts: { [key: string]: any }) { 101 | return function (engine, locale) { 102 | const o: { [key: string]: any } = {}; 103 | Object.keys(opts).forEach(k => { 104 | const arbOrValue = opts[k]; 105 | if (arbOrValue instanceof Arbitrary) { 106 | o[k] = arbOrValue.makeGenerator()(engine, locale); 107 | } 108 | else { 109 | o[k] = arbOrValue; 110 | } 111 | }); 112 | return o; 113 | }; 114 | }, 115 | genOpts: spec 116 | }).set('name', 'Object'); 117 | } -------------------------------------------------------------------------------- /src/combinators/eval.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { int } from '../types/primitive/index'; 3 | import { 4 | call 5 | } from './eval'; 6 | 7 | describe('Eval Combinator', () => { 8 | describe('Call', () => { 9 | it('works', () => { 10 | const xprime = call((x: number) => x, int).random; 11 | expect(Number.isInteger(xprime)).eq(true); 12 | }); 13 | }); 14 | }); -------------------------------------------------------------------------------- /src/combinators/eval.ts: -------------------------------------------------------------------------------- 1 | import { Arbitrary} from '../arbitrary'; 2 | import { sequence } from './collections'; 3 | 4 | /** 5 | * Produces an instance of class C. 6 | */ 7 | export function impl([constructor, ...args]: any[]) { 8 | return sequence(...args) 9 | .transform(args => new constructor(...args)) 10 | .set('name', 'Impl'); 11 | } 12 | 13 | /** 14 | * Produces an value of function with given arguments. 15 | */ 16 | export function call(fn: Function, ...args: any[]) { 17 | return sequence(...args) 18 | .transform(args => fn(...args)) 19 | .set('name', 'Call'); 20 | } -------------------------------------------------------------------------------- /src/combinators/func.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { func, genfunc } from './func'; 3 | 4 | describe('Func Combinator', () => { 5 | describe('Function', () => { 6 | describe('#random', () => { 7 | it('produces', () => { 8 | expect(typeof func).eq('function'); 9 | }); 10 | }); 11 | }); 12 | describe('GenFunction', () => { 13 | describe('#random', () => { 14 | it('produces', () => { 15 | expect(typeof genfunc().random().next).eq('function'); 16 | }); 17 | }); 18 | }); 19 | }); -------------------------------------------------------------------------------- /src/combinators/func.ts: -------------------------------------------------------------------------------- 1 | import { Engine } from 'random-js'; 2 | import { Arbitrary } from '../arbitrary'; 3 | import { oneOf } from './pickers'; 4 | import { array } from './collections'; 5 | import { bool, any } from '../types/primitive/index'; 6 | 7 | /** 8 | * Produce a function. 9 | */ 10 | export function func(out = oneOf([any, array()])) { 11 | return new Arbitrary({ 12 | gen: (arb: Arbitrary) => (engine, locale) => { 13 | return function () { 14 | return arb.makeGenerator()(engine, locale); 15 | } 16 | }, 17 | genOpts: out 18 | }).set('name', 'Function'); 19 | } 20 | 21 | /** 22 | * Produce a TypeScript Generator. 23 | */ 24 | export function genfunc(out = oneOf([any, array()])) { 25 | return new Arbitrary({ 26 | gen: (arb: Arbitrary) => (engine, locale) => { 27 | return function* () { 28 | yield arb.makeGenerator()(engine, locale); 29 | } 30 | }, 31 | genOpts: out 32 | }).set('name', 'Generator Function'); 33 | } 34 | 35 | export type PromiseGenOpts = { 36 | data: any, 37 | error: any, 38 | failrate: number 39 | }; 40 | 41 | function promiseGen(opts: PromiseGenOpts) { 42 | return function (engine: Engine, locale: string) { 43 | return new Promise(function (resolve, reject) { 44 | const fail = bool.choose(opts.failrate).makeGenerator()(engine, locale); 45 | return fail ? reject(opts.error) : resolve(opts.data); 46 | }); 47 | } 48 | } 49 | 50 | /** 51 | * Produces a Promise. 52 | */ 53 | export function promise(data: Arbitrary, error?: any) { 54 | return new Arbitrary({ 55 | gen: promiseGen, 56 | genOpts: { 57 | data: data, 58 | error: error || 'promiseFail', 59 | failrate: 50 60 | } 61 | }).set('name', 'Promise'); 62 | } -------------------------------------------------------------------------------- /src/combinators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './collections'; 2 | export * from './pickers'; 3 | export * from './func'; 4 | export * from './eval'; 5 | export * from './value'; -------------------------------------------------------------------------------- /src/combinators/picker.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { 3 | int, 4 | hexString 5 | } from '../types/primitive/index'; 6 | import { 7 | elements, 8 | oneOf, 9 | frequency 10 | } from './pickers'; 11 | 12 | describe('Picker Combinator', () => { 13 | describe('Elements', () => { 14 | describe('#random', () => { 15 | it('produces', () => { 16 | const v = elements([1, 'a',]).random; 17 | expect(v === 1 || v === 'a').eq(true); 18 | }) 19 | }); 20 | }) 21 | describe('OneOf', () => { 22 | describe('#random', () => { 23 | it('produces', () => { 24 | const v = oneOf([int, hexString]).random; 25 | expect(typeof v === 'number' || typeof v === 'string').eq(true); 26 | }) 27 | }); 28 | }); 29 | describe('Frequency', () => { 30 | it('works', () => { 31 | const x = frequency([[4, 5], [9, int]]).random; 32 | expect(Number.isInteger(x)).eq(true); 33 | }); 34 | }); 35 | }); -------------------------------------------------------------------------------- /src/combinators/pickers.ts: -------------------------------------------------------------------------------- 1 | import { Arbitrary } from '../arbitrary'; 2 | import { sum } from 'lodash'; 3 | import { Engine, integer, picker } from 'random-js'; 4 | 5 | /** 6 | * Generates one of the given values. The input list must be non-empty. 7 | */ 8 | export function elements(pool: any[]) { 9 | return new Arbitrary({ 10 | gen: (opts: any[]) => 11 | (engine:Engine) => 12 | picker(opts || pool)(engine), 13 | genOpts: pool 14 | }).set('name', 'Elements'); 15 | } 16 | 17 | /** 18 | * Options Of OneOf Gen. 19 | */ 20 | export type oneOfGenOpts = Arbitrary[]; 21 | 22 | /** 23 | * Randomly uses one of the given generators. The input list must be non-empty. 24 | */ 25 | export function oneOf(arbs: oneOfGenOpts) { 26 | return elements(arbs).transform( 27 | (result , engine, locale) => 28 | result.makeGenerator()(engine, locale) 29 | ).set('name', 'OneOf'); 30 | } 31 | 32 | export type FrequencyGenOpts = Array<[number, any]>; 33 | 34 | /** 35 | * Choose one of the given arbitrary(s), with a weighted random distribution. 36 | * The input list must be non-empty. 37 | */ 38 | export function frequency(pool: FrequencyGenOpts) { 39 | return new Arbitrary({ 40 | gen: function (pool: FrequencyGenOpts) { 41 | return function (engine, locale) { 42 | function pick(n: number, [[k, x], ...xs]): any { 43 | return (n <= k) ? x : pick(n - k, xs); 44 | } 45 | const total = sum(pool.map(e => e[0])); 46 | const head = integer(1, total)(engine); 47 | const result = pick(head, pool); 48 | if (result instanceof Arbitrary) { 49 | return result.makeGenerator()(engine, locale); 50 | } 51 | else { 52 | return result; 53 | }; 54 | }; 55 | }, 56 | genOpts: pool 57 | }).set('name', 'Frequency'); 58 | } -------------------------------------------------------------------------------- /src/combinators/value.ts: -------------------------------------------------------------------------------- 1 | let RandExp = require('randexp'); 2 | import { integer } from 'random-js'; 3 | import { Arbitrary } from '../arbitrary'; 4 | import { oneOf } from './pickers'; 5 | 6 | /** 7 | * Generates a constant value. 8 | */ 9 | export function constant(value: any) { 10 | return new Arbitrary({ 11 | gen: () => () => value 12 | }).set('name', 'Constant'); 13 | } 14 | 15 | /** 16 | * Options of RegexGenOpts 17 | */ 18 | export type RegexGenOpts = { 19 | ignoreCase: boolean, 20 | multiline: boolean 21 | } 22 | 23 | /** 24 | * Produces regex. 25 | * @XXX: get rid of randexp. 26 | */ 27 | export function regex(pattern: string) { 28 | return new Arbitrary({ 29 | gen: function (opts: RegexGenOpts) { 30 | return function (engine) { 31 | const m = []; 32 | if (opts.ignoreCase) m.push('i'); 33 | if (opts.multiline) m.push('m'); 34 | const randexp = new RandExp(pattern, m.join()); 35 | randexp.randInt = (from: number, to: number) => { 36 | return integer(from, to)(engine); 37 | } 38 | return randexp.gen(); 39 | } 40 | }, 41 | genOpts: { 42 | ignoreCase: false, 43 | multiline: false 44 | } 45 | }) 46 | } 47 | 48 | /** 49 | * An arbitrary returns a value or null. 50 | */ 51 | export function maybe(arb: Arbitrary) { 52 | return oneOf([arb, constant(null)]).set('name', 'Maybe'); 53 | } -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | import * as Random from 'random-js'; 2 | 3 | /** 4 | * Options specifies arguments to the checker. 5 | * 6 | * @property tests The max number of tests 7 | * @property engine A random-js engine 8 | */ 9 | export interface CheckOptions { 10 | tests: number; 11 | engine: Random.MT19937; 12 | seed: number, 13 | locale: string; 14 | format: boolean 15 | } 16 | 17 | /** 18 | * Create default random engine. 19 | */ 20 | const seed = process.env.SEED || new Date().getTime(); 21 | const engine = Random.engines.mt19937() 22 | engine.seed(seed); 23 | 24 | /** 25 | * The default check options. 26 | */ 27 | export const stdOpts: CheckOptions = { 28 | tests : 50, 29 | engine : engine, 30 | seed: seed, 31 | locale : 'en', 32 | format: true 33 | }; -------------------------------------------------------------------------------- /src/definition.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import * as _ from 'lodash'; 3 | import { Definitions } from './definition'; 4 | 5 | describe('Definitions', () => { 6 | const defs = new Definitions({ 7 | en: { 8 | regex: [/[0-9]{2,3}/], 9 | name: [1, 2, 3], 10 | nest: { 11 | nest1: 12 | ['a', 'b'] 13 | } 14 | }, 15 | zh_Hant_TW: { 16 | name: [4, 5, 6] 17 | } 18 | }); 19 | 20 | describe('#get()', () => { 21 | it('get a definition', () => { 22 | expect(defs.get('name')).eql([1, 2, 3]); 23 | expect(defs.get('name', 'en')).eql([1, 2, 3]); 24 | expect(defs.get('name', 'zh-Hant-TW')).eql([4, 5, 6]); 25 | }) 26 | }); 27 | 28 | describe('#arbitrary()', () => { 29 | it('makes arbitrary', () => { 30 | const arb = defs.arbitrary('name'); 31 | const a = arb.random; 32 | const b = arb.locale('zh-Hant-TW').random; 33 | expect([1, 2, 3].indexOf(a) >= 0).eq(true); 34 | expect([4, 5, 6].indexOf(b) >= 0).eq(true); 35 | const arb2 = defs.arbitrary('nest.nest1'); 36 | expect(['a', 'b'].indexOf(arb2.random) >= 0).eq(true); 37 | }); 38 | }); 39 | 40 | describe('#formatter()', () => { 41 | it("makes a arbitrary of an array of regex string", () => { 42 | const arb = defs.arbitrary('regex'); 43 | expect(_.isNumber(Number(arb.random))).eq(true); 44 | }); 45 | }); 46 | 47 | }); -------------------------------------------------------------------------------- /src/definition.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | import { 3 | get, 4 | isRegExp, 5 | template 6 | } from 'lodash'; 7 | import { Engine } from 'random-js'; 8 | import { Arbitrary } from './arbitrary'; 9 | import { 10 | elements, 11 | regex 12 | } from './combinators/index'; 13 | 14 | /** 15 | * Definitions Data 16 | * * 17 | * the structure of data looks like 18 | * {en: {name1: val1}, zh_Hant_TW: {name1: val1}} 19 | */ 20 | export type DefinitionsData = Object; 21 | export type Definition = any[] | Function; 22 | export type Formatter = (result: any, locale: string, engine: Engine) => string; 23 | 24 | function definitionGen(definitions: Definitions) { 25 | return (name: string) => (engine: Engine, locale: string) => { 26 | let pool = definitions.get(name, locale); 27 | if (Array.isArray(pool)) { 28 | pool = pool.map((s: string) => { 29 | return isRegExp(s) ? regex(s).makeGenerator()(engine) : s; 30 | }); 31 | return elements(pool).makeGenerator()(engine, locale); 32 | } 33 | else { 34 | return pool; 35 | } 36 | }; 37 | } 38 | /** 39 | * Extra definitions manager. 40 | * 41 | * A definition is an array of any values/regular expression or a function. 42 | */ 43 | export class Definitions { 44 | protected _data: Object; 45 | constructor(data: DefinitionsData) { 46 | this._data = data; 47 | } 48 | /** 49 | * Load a definitions. 50 | */ 51 | static load(path: string) { 52 | return new Definitions(require(resolve(path))); 53 | } 54 | /** 55 | * Get a definition. 56 | */ 57 | get(name: string, locale = 'en'): Definition { 58 | const _locale = locale.replace(/-/g, '_'); 59 | const q = `${_locale}.${name}`; 60 | return get(this._data, q); 61 | } 62 | /** 63 | * Create an arbitrary from a definition. 64 | */ 65 | arbitrary(name: string): Arbitrary { 66 | return new Arbitrary({ 67 | gen: definitionGen(this), 68 | genOpts: name 69 | }); 70 | } 71 | /** 72 | * Create a special arbitrary transform function for formating 73 | * the result generated by a arbitrary. 74 | */ 75 | formatter(name: string): Formatter { 76 | return (result: any, engine: Engine, locale: string) => { 77 | let f = this.get(name, locale); 78 | if (Array.isArray(f)) { 79 | f = template(elements(f).makeGenerator()(engine)); 80 | } 81 | return f(result); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /src/gen.ts: -------------------------------------------------------------------------------- 1 | import { Engine, uuid4 } from 'random-js'; 2 | 3 | /** 4 | * A function to produce a random value. 5 | */ 6 | export type Generator = (engine: Engine, locale?: string) => ValueT; 7 | 8 | /** 9 | * A function to produce a Generator. 10 | */ 11 | export type Gen = (genOpts?: GenOptsT) => Generator; 12 | 13 | export function mkGen(generator: Generator) { 14 | return (opts: O) => generator; 15 | } 16 | 17 | /** 18 | * A function to transform produced value. 19 | */ 20 | export type ValueTransform 21 | = (v: FromValueT, engine: Engine, locale: string) => TargetValueT; 22 | 23 | /** 24 | * A function to transform Gen A to Gen B. 25 | */ 26 | export type GenTransform 27 | = (gen: Gen) => 28 | Gen 29 | 30 | /** 31 | * A function to transform GenOpts A to GenOpts B. 32 | */ 33 | export type GenOptsTransform 34 | = (genOpts: FromGenOptsT | null) => TargetGenOptsT; 35 | 36 | /** 37 | * Promote a pure function as GenTransform. 38 | */ 39 | export function promote( 40 | f: ValueTransform 41 | ): GenTransform { 42 | return (gen: Gen) => { 43 | return (genOpts: FO) => { 44 | return (engine: Engine, locale: string) => { 45 | return f(gen(genOpts)(engine, locale), engine, locale); 46 | }; 47 | }; 48 | }; 49 | } 50 | 51 | /** 52 | * A function to test a value. 53 | */ 54 | export type ValuePredication = (v: V) => boolean; 55 | 56 | /** 57 | * Transform predicate function as SuchThatGenTransform. 58 | */ 59 | export function suchThat( 60 | predicate: ValuePredication 61 | ): GenTransform { 62 | return gen => (opts: FO) => { 63 | return (engine: Engine, locale: string) => { 64 | let x; 65 | let j = 0; 66 | for (let i = 0; ; i++) { 67 | j++; 68 | if (i > 5) { 69 | i = 0; 70 | } 71 | x = gen(opts)(engine, locale); 72 | if (j > 5000) { 73 | throw new Error('cant not find value in this range'); 74 | } 75 | if (predicate(x)) { 76 | break; 77 | } 78 | } 79 | return x; 80 | }; 81 | }; 82 | } -------------------------------------------------------------------------------- /src/idnex.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hychen/ke-e/2a632975014f92b8def0a2caf4020fb2332e8ddf/src/idnex.d.ts -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as C from './combinators'; 2 | import * as T from './types/index'; 3 | import * as S from './seq'; 4 | import { Arbitrary } from './arbitrary'; 5 | import hold from './integrations/index'; 6 | import { property, TestResult, forAll, ForAll } from './property'; 7 | 8 | const namespace = Object.assign({}, C, T, { 9 | seq: S, 10 | forAll: forAll, 11 | property: property, 12 | hold: hold, 13 | register: function register(name: string, module: Object) { 14 | if (namespace.hasOwnProperty(name)) { 15 | throw new Error(`${name} is registered.`); 16 | } 17 | namespace[name] = module; 18 | return true; 19 | } 20 | }); 21 | 22 | export default namespace; -------------------------------------------------------------------------------- /src/integrations/index.ts: -------------------------------------------------------------------------------- 1 | import { Predicate } from '../property'; 2 | import { hold as mochaHold } from './mocha'; 3 | 4 | export default function hold(name: string, predicate: Predicate) { 5 | // running with mocha; 6 | if (typeof it !== 'undefined') { 7 | return mochaHold.apply(null, arguments); 8 | } 9 | else { 10 | throw new Error('Oops!'); 11 | } 12 | } -------------------------------------------------------------------------------- /src/integrations/mocha.test.ts: -------------------------------------------------------------------------------- 1 | import { string, int } from '../types/primitive/index'; 2 | import hold from './index'; 3 | 4 | describe('Mocha Integration', () => { 5 | hold('works', 6 | (x: number, y:number) => x + y === y + x, 7 | ) 8 | .over(int, int) 9 | }); -------------------------------------------------------------------------------- /src/integrations/mocha.ts: -------------------------------------------------------------------------------- 1 | import { ok } from 'assert'; 2 | import { stdOpts } from '../constants'; 3 | import { 4 | Predicate, 5 | property, 6 | safeCheck, 7 | formatCheckResult 8 | } from '../property'; 9 | 10 | function mochaTestIt(name: string, pf: Predicate) { 11 | const test = { 12 | over: function (...qs: any[]) { 13 | it(name, async function () { 14 | const r = await safeCheck(property(pf, ...qs), stdOpts); 15 | ok(r.ok, formatCheckResult(r)); 16 | }); 17 | return test; 18 | } 19 | }; 20 | return test; 21 | } 22 | 23 | export function hold(name: string, predicate: Predicate) { 24 | return mochaTestIt(name, predicate); 25 | } -------------------------------------------------------------------------------- /src/property.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { stdOpts } from './constants'; 3 | import * as P from './property'; 4 | import { int, nat } from './types/primitive/number'; 5 | 6 | describe('property', () => { 7 | describe('property()', () => { 8 | it('returns a Prop', () => { 9 | const p = P.property((x:number) => x === 1, int); 10 | expect(!!p).eq(true); 11 | }); 12 | }); 13 | describe('apply()', () => { 14 | it('return succeed result if the predicate is true', async () => { 15 | const r = await P.apply((x:number, y:number) => 16 | x + y === y + x, 17 | [1, 2]); 18 | expect(r.ok).eq(true); 19 | }); 20 | it('return fail result if the predicate is false ', async () => { 21 | const r = await P.apply((x:number, y:number) => 22 | x !== y, 23 | [1, 2]); 24 | expect(r.ok).eq(true); 25 | }); 26 | it('catches an exception thrown by the predicate', async () => { 27 | const r = await P.apply(() => { 28 | throw new Error('hi'); 29 | }, []); 30 | expect(r.theException).eql(new Error('hi')); 31 | }); 32 | }); 33 | describe('check()', () => { 34 | it('runs 100 property tests', async () => { 35 | const p = P.property((x:number) => typeof x === 'number', int); 36 | const r = await P.check(p, stdOpts); 37 | expect(r.indexOf('+ Ok, pass 50 tests')).gte(0); 38 | }); 39 | it('failed if first property test raises an exception', async () => { 40 | const p = P.property((x: number) => { 41 | throw new Error('hi'); 42 | } , int); 43 | const r = await P.check(p, stdOpts); 44 | expect(r.indexOf('Fail')).gte(0); 45 | expect(r.indexOf('Error')).gte(0); 46 | }); 47 | it('returns check result', async () => { 48 | const p = P.property((x: number) => x*x < 0, int); 49 | const r = await P.check(p, Object.assign(stdOpts, { format: false })); 50 | expect(r.ok).eq(false); 51 | expect(r.tests).eq(1); 52 | expect(!!r.samples).eq(true); 53 | }); 54 | }); 55 | describe('ForAll', () => { 56 | describe('#eval()', () => { 57 | it('applies generated values to a function.', () => { 58 | const x = P.forAll(int).eval((x:number) => x + 1); 59 | expect(typeof x).eq('number'); 60 | }); 61 | }); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /src/property.ts: -------------------------------------------------------------------------------- 1 | import { every } from 'lodash'; 2 | import { Engine } from 'random-js'; 3 | import { stdOpts, CheckOptions } from './constants'; 4 | import { Arbitrary } from './arbitrary'; 5 | import { shrinkNoop } from './shrink'; 6 | import { take, join, Seq } from './seq'; 7 | 8 | /** 9 | * A result of property test. 10 | */ 11 | export interface TestResult { 12 | // The result of test. 13 | ok: boolean, 14 | // The input samples. 15 | samples: any[] 16 | // the exception thrown, if any. 17 | theException: Error | null, 18 | } 19 | 20 | /** 21 | * Succeed Result. 22 | */ 23 | function succeed(samples: any[]): TestResult { 24 | return { 25 | ok: true, 26 | samples: samples, 27 | theException: null 28 | }; 29 | } 30 | 31 | /** 32 | * Failed Result. 33 | */ 34 | function failed(samples: any[], error = null): TestResult { 35 | return { 36 | ok: false, 37 | samples: samples, 38 | theException: error 39 | } 40 | } 41 | 42 | /** 43 | * A predicate takes an entity or entities in the domain of discourse as input 44 | * and outputs either True or False. 45 | */ 46 | export type Predicate = Function; 47 | 48 | /** 49 | * A property is a promise like Generator, but generate a 50 | * test result. 51 | */ 52 | export type Property = (engine: Engine, locale: string) => Promise; 53 | 54 | /** 55 | * Apply a predicate to an given samples. 56 | */ 57 | export async function apply(predicate: Function, samples: any[]): Promise { 58 | return new Promise((resolve, reject) => { 59 | try { 60 | const r = predicate.apply(null, samples); 61 | resolve(r ? succeed(samples) : failed(samples)); 62 | } catch (error) { 63 | resolve(failed(samples, error)); 64 | } 65 | }); 66 | } 67 | 68 | export async function shrink(predicate: Function, failure: TestResult, shrunkens: Seq): Promise { 69 | return new Promise(async (resolve, reject) => { 70 | let samples = take(shrunkens, 1); 71 | if (samples.length === 0) return resolve(failure); 72 | let r = await apply(predicate, samples[0]); 73 | if (r.ok) return resolve(failure); 74 | return resolve(await shrink(predicate, r, shrunkens)); 75 | }); 76 | } 77 | 78 | /** 79 | * Check Result. 80 | */ 81 | export interface CheckResult { 82 | ok: boolean, 83 | tests: number, 84 | pass: number, 85 | samples: any[] | null, 86 | theException: Error | null, 87 | seed: number 88 | } 89 | 90 | /** 91 | * Check the property. 92 | */ 93 | export async function check(property: Property, opts: CheckOptions) { 94 | const result = await safeCheck(property, opts); 95 | return opts.format ? formatCheckResult(result) : result; 96 | } 97 | 98 | export async function safeCheck(property: Property, opts: CheckOptions) { 99 | opts.engine.seed(opts.seed); 100 | // Run a property to catch an exception as 101 | // easier as possible. 102 | const safe = await property(opts.engine, opts.locale); 103 | return safe.ok ? await checkWith(property, opts) : { 104 | ok: false, 105 | tests: 1, 106 | pass: 0, 107 | samples: safe.samples, 108 | theException: safe.theException, 109 | seed: opts.seed 110 | }; 111 | } 112 | 113 | export async function checkWith(property: Property, opts: CheckOptions) { 114 | const tests = []; 115 | for (let i = 0; i < opts.tests; i++) { 116 | tests.push(property(opts.engine, opts.locale)); 117 | } 118 | const results = await Promise.all(tests); 119 | const total = results.length; 120 | let pass = 0; 121 | for(let i = 0; i < total; i++) { 122 | if (results[i].ok) { 123 | pass += 1 124 | } 125 | } 126 | let samples = null; 127 | if (total !== pass) { 128 | const r = results.find(r => !r.ok); 129 | if (!!r) { 130 | samples = r.samples; 131 | } 132 | } 133 | return { 134 | ok: total === pass, 135 | tests: total, 136 | pass: pass, 137 | samples: samples, 138 | theException: null, 139 | seed: opts.seed 140 | }; 141 | } 142 | 143 | /** 144 | * Format the results. 145 | */ 146 | export function formatCheckResult(result: CheckResult): string { 147 | const msg = []; 148 | msg.push(result.ok ? '+ Ok' : '+ Fail'); 149 | msg.push(', '); 150 | msg.push(`pass ${result.pass} tests`); 151 | msg.push(', '); 152 | msg.push(`seed: ${result.seed}`); 153 | msg.push(`, `); 154 | msg.push(`samples: ${result.samples}`); 155 | msg.push('\n'); 156 | if (result.theException) { 157 | msg.push(result.theException.stack); 158 | } 159 | return msg.join(''); 160 | } 161 | 162 | /** 163 | * Create a property. 164 | */ 165 | export function property( 166 | predicate: Predicate, 167 | ...quantifiers: Arbitrary[]) { 168 | return new ForAll(quantifiers).predicate(predicate).makeProperty(); 169 | }; 170 | 171 | /** 172 | * Constructor a ForAll. 173 | */ 174 | export function forAll(...arbs: Arbitrary[]) { 175 | return new ForAll(arbs); 176 | }; 177 | 178 | /** 179 | * The thing which can be tested, 180 | */ 181 | export class ForAll { 182 | _predicate: Predicate; 183 | quantifiers: Arbitrary[]; 184 | /** 185 | * Make a Prop. 186 | */ 187 | constructor(quantifiers: Arbitrary[]) { 188 | this.quantifiers = quantifiers; 189 | } 190 | /** 191 | * Set predicate. 192 | */ 193 | predicate(pf: Predicate) { 194 | if (pf.length !== this.quantifiers.length) { 195 | throw new Error('quantifiers parameter do not match signature of predicate'); 196 | } 197 | this._predicate = pf; 198 | return this; 199 | } 200 | /** 201 | * Generate sample values. 202 | */ 203 | makeSamples(engine: Engine, locale: string): any[] { 204 | const samples = this.quantifiers.map( 205 | q => q.makeGenerator()(engine, locale) 206 | ); 207 | return samples; 208 | } 209 | makeShrunkens(seeds: any[], locale: string): Seq { 210 | const shrinkers = this.quantifiers.map( 211 | q => q.shrinker || shrinkNoop 212 | ); 213 | const seqs = seeds.map((v, i) => shrinkers[i](v)); 214 | return join(seqs); 215 | } 216 | /** 217 | * Convert the thing to a property. 218 | */ 219 | makeProperty(): Property { 220 | return async (engine, locale) => { 221 | const r = await apply(this._predicate, this.makeSamples(engine, locale)); 222 | if (r.ok) { 223 | return r; 224 | } else { 225 | return await shrink(this._predicate, r, this.makeShrunkens(r.samples, locale)); 226 | } 227 | }; 228 | } 229 | /** 230 | * Evaluate the function with quantifiers. 231 | */ 232 | eval(f: Function, opts = stdOpts) { 233 | return f.apply(null, this.makeSamples(opts.engine, opts.locale)); 234 | } 235 | /** 236 | * Check this property. 237 | */ 238 | check(opts = stdOpts) { 239 | check(this.makeProperty(), opts).then(console.log).catch(console.error); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/seq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A generator to simulate Lazy-Seq 3 | * 4 | * @FIXME: use real lazy seq. 5 | */ 6 | export type Seq = IterableIterator; 7 | 8 | export function * fold(f: Function, seq: Seq, acc?: any) { 9 | let v = seq.next(); 10 | while(!v.done) { 11 | yield f(v.value, acc); 12 | v = seq.next(); 13 | }; 14 | } 15 | 16 | export function * filter(f:Function, seq: Seq) { 17 | let v = seq.next(); 18 | while(!v.done) { 19 | if (f(v.value)) 20 | yield v.value; 21 | v = seq.next(); 22 | } 23 | } 24 | 25 | export function * map(f: Function, seq: Seq) { 26 | return fold(f, seq); 27 | } 28 | 29 | export function take(seq: Seq, n: number) { 30 | const result = []; 31 | let i = 1; 32 | let v = seq.next(); 33 | while(i <= n && !v.done) { 34 | result.push(v.value); 35 | v = seq.next(); 36 | i++; 37 | } 38 | return result; 39 | } 40 | 41 | export function * fromArray(arr: any[]) { 42 | for(let i = 0; i < arr.length; i++) { 43 | yield arr[i]; 44 | } 45 | } 46 | 47 | export function toArray(seq: Seq) { 48 | return take(seq, Infinity); 49 | }; 50 | 51 | export function * join(seqs: Seq[]): Seq { 52 | while (true) { 53 | let values = Array(seqs.length); 54 | for (let i = 0; i < seqs.length; ++i) { 55 | let v = take(seqs[i], 1); 56 | if (v.length === 0) { 57 | return; 58 | } 59 | values[i] = v[0]; 60 | } 61 | yield values; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/shrink.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import * as seq from './seq'; 3 | import * as shrink from './shrink'; 4 | 5 | describe('shrink', () => { 6 | describe('shrinkNumber', () => { 7 | it('returns Iterator<[]> if x = 0', () => { 8 | const a = seq.toArray(shrink.shrinkNumber(0)); 9 | expect(a).eql([]); 10 | }) 11 | it('last value is less than x if x > 0', () => { 12 | const s1 = shrink.shrinkNumber(70); 13 | expect(s1.next().value).lt(70); 14 | }); 15 | it('first value is x if x < 0', () => { 16 | const s = shrink.shrinkNumber(-70); 17 | expect(s.next().value).eql(70); 18 | }); 19 | it('last value greater is than x if x < 0', () => { 20 | const s1 = shrink.shrinkNumber(-70); 21 | expect(s1.next().value).gt(-70); 22 | }); 23 | }); 24 | describe('filter', () => { 25 | it('returns a seq that the values satisfy f', () => { 26 | const s = seq.filter((n: number) => n < 0, shrink.shrinkNumber(-70)); 27 | expect(seq.toArray(s)).eql([-35, -53, -62, -66, -68, -69]); 28 | }); 29 | }); 30 | }); -------------------------------------------------------------------------------- /src/shrink.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Produces a (possibly) empty list of all the possible immediate shrinks of the given value. 3 | 4 | Most implementations of shrinker should try at least three things: 5 | 6 | 1. Shrink a term to any of its immediate subterms. 7 | 2. Recursively apply shrink to all immediate subterms. 8 | 3. Type-specific shrinkings such as replacing a constructor by a simpler constructor. 9 | **/ 10 | import { Seq } from './seq'; 11 | import { div2 } from './utils'; 12 | 13 | export type Shrinker = (v: V) => Seq; 14 | 15 | export function * shrinkNoop() { 16 | yield null; 17 | } 18 | 19 | /** 20 | * A function to reducing failed examples to their minimal form. 21 | */ 22 | export function * shrinkNumber(x: number): Seq { 23 | if (x === 0) return null; 24 | // abs a < abs b 25 | const less = (a: number, b: number) => { 26 | if (a >= 0 && b >= 0) return a < b; 27 | if (a < 0 && b < 0) return a > b; 28 | if (a >=0 && b < 0) return a + b < 0; 29 | if (a < 0 && b >= 0) return a + b > 0; 30 | throw new Error('should not reach here.'); 31 | } 32 | if (x < 0 && -x > x) yield -x; 33 | yield 0; 34 | // find initial gap. 35 | let i = div2(x); 36 | let j = i; 37 | while(less(j, x)) { 38 | // calculate the value. 39 | j = x - i; 40 | // yield the value if it is not itself. 41 | if (j !== x) yield j; 42 | // update gap. 43 | i = div2(i); 44 | } 45 | } -------------------------------------------------------------------------------- /src/traits.ts: -------------------------------------------------------------------------------- 1 | export type Source = {[key: string]: any}; 2 | 3 | export class Chainable { 4 | protected attrs: T & {[key: string]: any}; 5 | get(k: string) { 6 | return this.attrs[k]; 7 | } 8 | /** 9 | * Set a private attribute. 10 | */ 11 | set(k: string, v: any): this { 12 | this.attrs[k] = v; 13 | return this; 14 | } 15 | /** 16 | * like Object.assign. 17 | */ 18 | assign(source: Source): Source { 19 | return Object.assign(this, source); 20 | }; 21 | } -------------------------------------------------------------------------------- /src/types/graphic/color.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | import { Arbitrary } from '../../arbitrary'; 5 | import { 6 | pint, 7 | num, 8 | NumberGenOpts, 9 | hexString, 10 | HexStringGenOpts 11 | } from '../primitive/index'; 12 | import { object } from '../../combinators'; 13 | 14 | const rgbRange = pint.choose({ max: 255 }); 15 | const hueRange = pint 16 | .choose({ max: 360 }) 17 | .transform(n => n / 360); 18 | const percent = pint.choose({ min: 0, max: 1 }); 19 | 20 | /** 21 | * Color RGBA 22 | * 23 | * @example 24 | * > ke.graphic.color.rgba.random 25 | * { red: 233.28651197533094, 26 | * green: 102.16220695801994, 27 | * blue: 14.784638255757336, 28 | * alpha: 0.3622623854661302 } 29 | */ 30 | const rgba = object({ 31 | red: rgbRange, 32 | green: rgbRange, 33 | blue: rgbRange, 34 | alpha: percent 35 | }).set('name', 'Color RGBA'); 36 | 37 | /** 38 | * Color HSVA 39 | */ 40 | const hsva = object({ 41 | hue: hueRange, 42 | saturation: percent, 43 | value: percent, 44 | alpha: percent 45 | }).set('name', 'Color HSVA'); 46 | 47 | /** 48 | * Color HSLA 49 | */ 50 | const hsla = object({ 51 | hue: hueRange, 52 | saturation: percent, 53 | lightness: percent, 54 | alpha: percent 55 | }).set('name', 'Color HSLA '); 56 | 57 | /** 58 | * Color Hex 59 | */ 60 | const hex = pint.choose({ min: 0x00000, max: 0xFFFFFF }) 61 | .set('name', 'Color Hex'); 62 | 63 | /** 64 | * Color HexCode 65 | * @example 66 | * > ke.graphic.color.hexCode.random 67 | * '#d7938d' 68 | */ 69 | const hexCode = hexString.transform(s => `#${s}`) 70 | .set('name', 'Color Hex Code'); 71 | 72 | export const color = { 73 | rgba, 74 | hsva, 75 | hsla, 76 | hex, 77 | hexCode 78 | } 79 | -------------------------------------------------------------------------------- /src/types/graphic/image.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | import { Arbitrary} from '../../arbitrary'; 5 | import {pint} from '../primitive/index'; 6 | import {elements, object} from '../../combinators'; 7 | 8 | interface lorempixURLOpts {width: number, height: number, category: string, gray: boolean}; 9 | 10 | function lorempixURL({width, height, category, gray}: lorempixURLOpts) { 11 | const grayPrefix = gray ? 'g/' : '' 12 | return `http://lorempixel.com/${grayPrefix}${width}/${height}/${category}`; 13 | } 14 | 15 | const imageCategory = elements([ 16 | 'abstract', 17 | 'animals', 18 | 'business', 19 | 'cats', 20 | 'city', 21 | 'food', 22 | 'nightlife', 23 | 'fashion', 24 | 'people', 25 | 'nature', 26 | 'sports', 27 | 'technics', 28 | 'transport' 29 | ]); 30 | 31 | /** 32 | * Image URL 33 | */ 34 | const imageURL = object({ 35 | width: 640, 36 | height: 480, 37 | category: imageCategory, 38 | gray: false 39 | }).transform(lorempixURL).set('name', 'Image URL'); 40 | 41 | /** 42 | * Gray Image URL 43 | */ 44 | const grayImageURL = imageURL 45 | .choose({gray: true}) 46 | .set('name', 'Gray Image URL'); 47 | 48 | export const image = { 49 | imageURL, 50 | grayImageURL 51 | } 52 | -------------------------------------------------------------------------------- /src/types/graphic/index.ts: -------------------------------------------------------------------------------- 1 | import { Arbitrary } from '../../arbitrary'; 2 | import { 3 | NumberGenOpts, 4 | HexStringGenOpts 5 | } from '../primitive/index'; 6 | import { color } from './color'; 7 | import { image } from './image'; 8 | export const graphic = {color, image}; 9 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './primitive/index'; 2 | export * from './locale/index'; 3 | export * from './person/index'; 4 | export * from './literate/index'; 5 | export * from './internet/index'; 6 | export * from './graphic/index'; 7 | export * from './location/index'; -------------------------------------------------------------------------------- /src/types/internet/definitions/en/index.ts: -------------------------------------------------------------------------------- 1 | export * from './avatarURI'; 2 | -------------------------------------------------------------------------------- /src/types/internet/definitions/index.ts: -------------------------------------------------------------------------------- 1 | import * as en from './en/index'; 2 | 3 | export default { 4 | en 5 | }; 6 | -------------------------------------------------------------------------------- /src/types/internet/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | import { Arbitrary } from '../../arbitrary'; 5 | import { 6 | oneOf, 7 | nearray, 8 | elements, 9 | object, 10 | constant 11 | } from '../../combinators'; 12 | import { Definitions } from '../../definition'; 13 | import { person } from '../person/index'; 14 | import { asciistring, nat } from '../primitive/index'; 15 | 16 | import definitions from './definitions/index'; 17 | const defs = new Definitions(definitions); 18 | 19 | const avatar = defs.arbitrary('avatarURI').set('name', 'Avatar URI'); 20 | 21 | const userNameSep = elements(['.', '_', '']); 22 | const userNameSuffix = oneOf([nat.choose({ min: 1, max: 99 }), constant('')]); 23 | const userNameSpec = { 24 | firstName: person.firstName, 25 | lastName: person.lastName, 26 | sep: userNameSep, 27 | suffix: userNameSuffix, 28 | chance: nat.choose({ min: 0, max: 1 }) 29 | }; 30 | 31 | /** 32 | * Arbitrary to produce internet user name. 33 | * @example 34 | * 35 | * // returns jack or jack.hand or jack.hand34. 36 | * ke.internet.userName.generate(); 37 | */ 38 | const userName = object(userNameSpec) 39 | .transform(r => { 40 | if (r.chance === 0) { 41 | return `${r.firstName}`; 42 | } 43 | else { 44 | return `${r.firstName}${r.sep}${r.lastName}${r.suffix}`; 45 | } 46 | }).set('name', 'Internet User Name'); 47 | 48 | /** 49 | * Arbitrary to produce a 16bit password. 50 | * @example 51 | * // returns JI|m)5?!e;"_b=$p 52 | * ke.internet.password.random 53 | */ 54 | const password = asciistring 55 | .choose({ min: 16, max: 16 }) 56 | .set('name', 'Password'); 57 | 58 | const freeEmailProvider = elements([ 59 | 'gmail.com', 60 | 'yahoo.com', 61 | 'hotmail.com' 62 | ]).set('name', 'Free Email Provider'); 63 | 64 | const emailSpec = { 65 | userName: userName, 66 | provider: freeEmailProvider 67 | }; 68 | 69 | /** 70 | * Arbitrary to produce an email. 71 | * @example 72 | * // returns jack.hand@gmail.com 73 | * ke.internet.email.generate(); 74 | */ 75 | const email = object(emailSpec) 76 | .transform(r => `${r.userName}@${r.provider}`) 77 | .set('name', 'Email'); 78 | 79 | const proto = elements(['http', 'https']).set('name', 'Internet Protocol'); 80 | 81 | const domainWord = person.firstName.transform((name: string) => { 82 | return name.replace(/([\\~#&*{}/:<>?|\"'])/ig, '').toLowerCase(); 83 | }).set('name', 'Domain Word'); 84 | 85 | const domainSuffix = elements([ 86 | 'com', 87 | 'org', 88 | 'io', 89 | 'info', 90 | 'today' 91 | ]).set('name', 'Domain Suffix'); 92 | 93 | const domainNameSpec = { 94 | domainWord, 95 | domainSuffix 96 | }; 97 | 98 | const domainName = object(domainNameSpec) 99 | .transform(r => `${r.domainWord}.${r.domainSuffix}`) 100 | .set('name', 'Domain Name'); 101 | 102 | const urlSpec = { 103 | proto, 104 | domainName 105 | }; 106 | 107 | /** 108 | * Arbitrary to produce an url. 109 | */ 110 | const url = object(urlSpec) 111 | .transform(r => `${r.proto}://${r.domainName}`) 112 | .set('name', 'URL'); 113 | 114 | const ipRange = nat.choose({ max: 255 }).set('name', 'IP Range'); 115 | 116 | /** 117 | * Arbitrary to produce an IP v4 address. 118 | */ 119 | const ip = nearray(ipRange).choose({ min: 3, max: 4 }) 120 | .transform(arr => arr.join('.')) 121 | .set('name', 'IP v4 Address'); 122 | 123 | const ipV6Range = nat.choose({ max: 15 }) 124 | .transform(n => n.toString(16)) 125 | .set('name', 'IPV6 Range'); 126 | 127 | const ipv6Block = nearray(ipV6Range) 128 | .choose({ min: 4, max: 4 }) 129 | .transform(arr => arr.join('')) 130 | .set('name', 'IPV6 Block'); 131 | 132 | /** 133 | * Arbitrary to produce an IP v6 address. 134 | */ 135 | const ipv6 = nearray(ipv6Block) 136 | .choose({ min: 8, max: 8 }) 137 | .transform(arr => arr.join(':')) 138 | .set('name', 'IP v5 Address'); 139 | 140 | export const internet = { 141 | avatar, 142 | userName, 143 | password, 144 | email, 145 | domainName, 146 | url, 147 | ip, 148 | ipv6 149 | }; 150 | -------------------------------------------------------------------------------- /src/types/literate/definitions/en/index.ts: -------------------------------------------------------------------------------- 1 | export const words = [ 2 | 'alias', 3 | 'consequatur', 4 | 'aut', 5 | 'perferendis', 6 | 'sit', 7 | 'voluptatem', 8 | 'accusantium', 9 | 'doloremque', 10 | 'aperiam', 11 | 'eaque', 12 | 'ipsa', 13 | 'quae', 14 | 'ab', 15 | 'illo', 16 | 'inventore', 17 | 'veritatis', 18 | 'et', 19 | 'quasi', 20 | 'architecto', 21 | 'beatae', 22 | 'vitae', 23 | 'dicta', 24 | 'sunt', 25 | 'explicabo', 26 | 'aspernatur', 27 | 'aut', 28 | 'odit', 29 | 'aut', 30 | 'fugit', 31 | 'sed', 32 | 'quia', 33 | 'consequuntur', 34 | 'magni', 35 | 'dolores', 36 | 'eos', 37 | 'qui', 38 | 'ratione', 39 | 'voluptatem', 40 | 'sequi', 41 | 'nesciunt', 42 | 'neque', 43 | 'dolorem', 44 | 'ipsum', 45 | 'quia', 46 | 'dolor', 47 | 'sit', 48 | 'amet', 49 | 'consectetur', 50 | 'adipisci', 51 | 'velit', 52 | 'sed', 53 | 'quia', 54 | 'non', 55 | 'numquam', 56 | 'eius', 57 | 'modi', 58 | 'tempora', 59 | 'incidunt', 60 | 'ut', 61 | 'labore', 62 | 'et', 63 | 'dolore', 64 | 'magnam', 65 | 'aliquam', 66 | 'quaerat', 67 | 'voluptatem', 68 | 'ut', 69 | 'enim', 70 | 'ad', 71 | 'minima', 72 | 'veniam', 73 | 'quis', 74 | 'nostrum', 75 | 'exercitationem', 76 | 'ullam', 77 | 'corporis', 78 | 'nemo', 79 | 'enim', 80 | 'ipsam', 81 | 'voluptatem', 82 | 'quia', 83 | 'voluptas', 84 | 'sit', 85 | 'suscipit', 86 | 'laboriosam', 87 | 'nisi', 88 | 'ut', 89 | 'aliquid', 90 | 'ex', 91 | 'ea', 92 | 'commodi', 93 | 'consequatur', 94 | 'quis', 95 | 'autem', 96 | 'vel', 97 | 'eum', 98 | 'iure', 99 | 'reprehenderit', 100 | 'qui', 101 | 'in', 102 | 'ea', 103 | 'voluptate', 104 | 'velit', 105 | 'esse', 106 | 'quam', 107 | 'nihil', 108 | 'molestiae', 109 | 'et', 110 | 'iusto', 111 | 'odio', 112 | 'dignissimos', 113 | 'ducimus', 114 | 'qui', 115 | 'blanditiis', 116 | 'praesentium', 117 | 'laudantium', 118 | 'totam', 119 | 'rem', 120 | 'voluptatum', 121 | 'deleniti', 122 | 'atque', 123 | 'corrupti', 124 | 'quos', 125 | 'dolores', 126 | 'et', 127 | 'quas', 128 | 'molestias', 129 | 'excepturi', 130 | 'sint', 131 | 'occaecati', 132 | 'cupiditate', 133 | 'non', 134 | 'provident', 135 | 'sed', 136 | 'ut', 137 | 'perspiciatis', 138 | 'unde', 139 | 'omnis', 140 | 'iste', 141 | 'natus', 142 | 'error', 143 | 'similique', 144 | 'sunt', 145 | 'in', 146 | 'culpa', 147 | 'qui', 148 | 'officia', 149 | 'deserunt', 150 | 'mollitia', 151 | 'animi', 152 | 'id', 153 | 'est', 154 | 'laborum', 155 | 'et', 156 | 'dolorum', 157 | 'fuga', 158 | 'et', 159 | 'harum', 160 | 'quidem', 161 | 'rerum', 162 | 'facilis', 163 | 'est', 164 | 'et', 165 | 'expedita', 166 | 'distinctio', 167 | 'nam', 168 | 'libero', 169 | 'tempore', 170 | 'cum', 171 | 'soluta', 172 | 'nobis', 173 | 'est', 174 | 'eligendi', 175 | 'optio', 176 | 'cumque', 177 | 'nihil', 178 | 'impedit', 179 | 'quo', 180 | 'porro', 181 | 'quisquam', 182 | 'est', 183 | 'qui', 184 | 'minus', 185 | 'id', 186 | 'quod', 187 | 'maxime', 188 | 'placeat', 189 | 'facere', 190 | 'possimus', 191 | 'omnis', 192 | 'voluptas', 193 | 'assumenda', 194 | 'est', 195 | 'omnis', 196 | 'dolor', 197 | 'repellendus', 198 | 'temporibus', 199 | 'autem', 200 | 'quibusdam', 201 | 'et', 202 | 'aut', 203 | 'consequatur', 204 | 'vel', 205 | 'illum', 206 | 'qui', 207 | 'dolorem', 208 | 'eum', 209 | 'fugiat', 210 | 'quo', 211 | 'voluptas', 212 | 'nulla', 213 | 'pariatur', 214 | 'at', 215 | 'vero', 216 | 'eos', 217 | 'et', 218 | 'accusamus', 219 | 'officiis', 220 | 'debitis', 221 | 'aut', 222 | 'rerum', 223 | 'necessitatibus', 224 | 'saepe', 225 | 'eveniet', 226 | 'ut', 227 | 'et', 228 | 'voluptates', 229 | 'repudiandae', 230 | 'sint', 231 | 'et', 232 | 'molestiae', 233 | 'non', 234 | 'recusandae', 235 | 'itaque', 236 | 'earum', 237 | 'rerum', 238 | 'hic', 239 | 'tenetur', 240 | 'a', 241 | 'sapiente', 242 | 'delectus', 243 | 'ut', 244 | 'aut', 245 | 'reiciendis', 246 | 'voluptatibus', 247 | 'maiores', 248 | 'doloribus', 249 | 'asperiores', 250 | 'repellat' 251 | ]; 252 | -------------------------------------------------------------------------------- /src/types/literate/definitions/index.ts: -------------------------------------------------------------------------------- 1 | import * as en from './en/index'; 2 | 3 | export default { 4 | en 5 | }; 6 | -------------------------------------------------------------------------------- /src/types/literate/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | import { Engine } from 'random-js'; 5 | import { Definitions } from '../../definition'; 6 | import { Arbitrary } from '../../arbitrary'; 7 | import { array, oneOf } from '../../combinators'; 8 | import { nat } from '../primitive/index'; 9 | 10 | import definitions from './definitions/index'; 11 | const defs = new Definitions(definitions); 12 | 13 | /** 14 | * Arbitrary to represent a word. 15 | */ 16 | const word = defs.arbitrary('words').set('name', 'Word'); 17 | 18 | /** 19 | * Arbitrary to represent a space separated list of words. 20 | */ 21 | const words = array(word).choose({ min: 3, max: 3 }) 22 | .transform((ws: string[]) => ws.join(' ')) 23 | .set('name', 'Words'); 24 | 25 | /** 26 | * Arbitrary to represent a sentence. 27 | */ 28 | const sentence = words.transform(s => { 29 | return s.charAt(0).toUpperCase() + s.slice(1) + '.'; 30 | }).set('name', 'Sentence'); 31 | 32 | type sentencesGenOpts = { 33 | min: number, 34 | max: number, 35 | sep: string 36 | }; 37 | 38 | function sentencesGen({ min, max, sep }: sentencesGenOpts) { 39 | return function (engine: Engine, locale: string) { 40 | const ss = array(sentence) 41 | .choose({ min: min, max: max }) 42 | .makeGenerator()(engine, locale); 43 | return ss.join(sep); 44 | }; 45 | }; 46 | 47 | /** 48 | * Arbitrary to represent a sentences. 49 | */ 50 | const sentences = new Arbitrary({ 51 | gen: sentencesGen, 52 | genOpts: { min: 2, max: 6, sep: ' ' } 53 | }).set('name', 'Sentences'); 54 | 55 | /** 56 | * Arbitrary to represent a paragraph. 57 | */ 58 | const paragraph = sentences.choose({ min: 3, max: 3 }).set('name', 'Paragraph'); 59 | 60 | type paragraphsGenOpts = { 61 | count: number, 62 | sep: string 63 | }; 64 | 65 | function paragraphsGen({ count, sep }: paragraphsGenOpts) { 66 | return function (engine: Engine, locale: string) { 67 | const ps = array(paragraph) 68 | .choose({ min: count, max: count }) 69 | .makeGenerator()(engine, locale); 70 | return ps.join(sep); 71 | }; 72 | } 73 | 74 | /** 75 | * Arbitrary to represent paragraphs separated by `'\n'`. 76 | * @type {Arbitrary} 77 | */ 78 | const paragraphs = new Arbitrary({ 79 | gen: paragraphsGen, 80 | genOpts: { count: 3, sep: '\r\n' } 81 | }).set('name', 'Paragraphs'); 82 | 83 | /** 84 | * Arbitrary to represent lines of sentences separated by `'\n'`. 85 | * @type {Arbitrary} 86 | */ 87 | const lines = sentences 88 | .choose({ min: 1, max: 5, sep: '\n' }) 89 | .set('name', 'Lines'); 90 | 91 | /** 92 | * Arbitrary to represent any text based string. 93 | * @type {Arbitrary} 94 | */ 95 | const text = oneOf([ 96 | word, 97 | sentence, 98 | sentences, 99 | paragraph, 100 | paragraphs, 101 | lines 102 | ]).set('name', 'Text'); 103 | 104 | export const literate = { 105 | word, 106 | words, 107 | sentence, 108 | sentences, 109 | paragraph, 110 | paragraphs, 111 | lines, 112 | text 113 | }; 114 | -------------------------------------------------------------------------------- /src/types/locale/avaliableLocaleids.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | 5 | /** 6 | * @describe available Locale Ids definition. 7 | * 8 | * Took from 9 | * https://github.com/unicode-cldr/cldr-core/blob/master/availableLocales.json. 10 | */ 11 | export default [ 12 | 'af', 13 | 'af-NA', 14 | 'am', 15 | 'ar', 16 | 'ar-AE', 17 | 'ar-BH', 18 | 'ar-DJ', 19 | 'ar-DZ', 20 | 'ar-EG', 21 | 'ar-EH', 22 | 'ar-ER', 23 | 'ar-IL', 24 | 'ar-IQ', 25 | 'ar-JO', 26 | 'ar-KM', 27 | 'ar-KW', 28 | 'ar-LB', 29 | 'ar-LY', 30 | 'ar-MA', 31 | 'ar-MR', 32 | 'ar-OM', 33 | 'ar-PS', 34 | 'ar-QA', 35 | 'ar-SA', 36 | 'ar-SD', 37 | 'ar-SO', 38 | 'ar-SS', 39 | 'ar-SY', 40 | 'ar-TD', 41 | 'ar-TN', 42 | 'ar-YE', 43 | 'az', 44 | 'az-Latn', 45 | 'be', 46 | 'bg', 47 | 'bn', 48 | 'bn-IN', 49 | 'bs', 50 | 'bs-Latn', 51 | 'ca', 52 | 'ca-AD', 53 | 'ca-ES-VALENCIA', 54 | 'ca-FR', 55 | 'ca-IT', 56 | 'cs', 57 | 'cy', 58 | 'da', 59 | 'da-GL', 60 | 'de', 61 | 'de-AT', 62 | 'de-BE', 63 | 'de-CH', 64 | 'de-IT', 65 | 'de-LI', 66 | 'de-LU', 67 | 'el', 68 | 'el-CY', 69 | 'en', 70 | 'en-001', 71 | 'en-150', 72 | 'en-AG', 73 | 'en-AI', 74 | 'en-AS', 75 | 'en-AT', 76 | 'en-AU', 77 | 'en-BB', 78 | 'en-BE', 79 | 'en-BI', 80 | 'en-BM', 81 | 'en-BS', 82 | 'en-BW', 83 | 'en-BZ', 84 | 'en-CA', 85 | 'en-CC', 86 | 'en-CH', 87 | 'en-CK', 88 | 'en-CM', 89 | 'en-CX', 90 | 'en-CY', 91 | 'en-DE', 92 | 'en-DG', 93 | 'en-DK', 94 | 'en-DM', 95 | 'en-ER', 96 | 'en-FI', 97 | 'en-FJ', 98 | 'en-FK', 99 | 'en-FM', 100 | 'en-GB', 101 | 'en-GD', 102 | 'en-GG', 103 | 'en-GH', 104 | 'en-GI', 105 | 'en-GM', 106 | 'en-GU', 107 | 'en-GY', 108 | 'en-HK', 109 | 'en-IE', 110 | 'en-IL', 111 | 'en-IM', 112 | 'en-IN', 113 | 'en-IO', 114 | 'en-JE', 115 | 'en-JM', 116 | 'en-KE', 117 | 'en-KI', 118 | 'en-KN', 119 | 'en-KY', 120 | 'en-LC', 121 | 'en-LR', 122 | 'en-LS', 123 | 'en-MG', 124 | 'en-MH', 125 | 'en-MO', 126 | 'en-MP', 127 | 'en-MS', 128 | 'en-MT', 129 | 'en-MU', 130 | 'en-MW', 131 | 'en-MY', 132 | 'en-NA', 133 | 'en-NF', 134 | 'en-NG', 135 | 'en-NL', 136 | 'en-NR', 137 | 'en-NU', 138 | 'en-NZ', 139 | 'en-PG', 140 | 'en-PH', 141 | 'en-PK', 142 | 'en-PN', 143 | 'en-PR', 144 | 'en-PW', 145 | 'en-RW', 146 | 'en-SB', 147 | 'en-SC', 148 | 'en-SD', 149 | 'en-SE', 150 | 'en-SG', 151 | 'en-SH', 152 | 'en-SI', 153 | 'en-SL', 154 | 'en-SS', 155 | 'en-SX', 156 | 'en-SZ', 157 | 'en-TC', 158 | 'en-TK', 159 | 'en-TO', 160 | 'en-TT', 161 | 'en-TV', 162 | 'en-TZ', 163 | 'en-UG', 164 | 'en-UM', 165 | 'en-US-POSIX', 166 | 'en-VC', 167 | 'en-VG', 168 | 'en-VI', 169 | 'en-VU', 170 | 'en-WS', 171 | 'en-ZA', 172 | 'en-ZM', 173 | 'en-ZW', 174 | 'es', 175 | 'es-419', 176 | 'es-AR', 177 | 'es-BO', 178 | 'es-BR', 179 | 'es-CL', 180 | 'es-CO', 181 | 'es-CR', 182 | 'es-CU', 183 | 'es-DO', 184 | 'es-EA', 185 | 'es-EC', 186 | 'es-GQ', 187 | 'es-GT', 188 | 'es-HN', 189 | 'es-IC', 190 | 'es-MX', 191 | 'es-NI', 192 | 'es-PA', 193 | 'es-PE', 194 | 'es-PH', 195 | 'es-PR', 196 | 'es-PY', 197 | 'es-SV', 198 | 'es-US', 199 | 'es-UY', 200 | 'es-VE', 201 | 'et', 202 | 'eu', 203 | 'fa', 204 | 'fa-AF', 205 | 'fi', 206 | 'fil', 207 | 'fo', 208 | 'fo-DK', 209 | 'fr', 210 | 'fr-BE', 211 | 'fr-BF', 212 | 'fr-BI', 213 | 'fr-BJ', 214 | 'fr-BL', 215 | 'fr-CA', 216 | 'fr-CD', 217 | 'fr-CF', 218 | 'fr-CG', 219 | 'fr-CH', 220 | 'fr-CI', 221 | 'fr-CM', 222 | 'fr-DJ', 223 | 'fr-DZ', 224 | 'fr-GA', 225 | 'fr-GF', 226 | 'fr-GN', 227 | 'fr-GP', 228 | 'fr-GQ', 229 | 'fr-HT', 230 | 'fr-KM', 231 | 'fr-LU', 232 | 'fr-MA', 233 | 'fr-MC', 234 | 'fr-MF', 235 | 'fr-MG', 236 | 'fr-ML', 237 | 'fr-MQ', 238 | 'fr-MR', 239 | 'fr-MU', 240 | 'fr-NC', 241 | 'fr-NE', 242 | 'fr-PF', 243 | 'fr-PM', 244 | 'fr-RE', 245 | 'fr-RW', 246 | 'fr-SC', 247 | 'fr-SN', 248 | 'fr-SY', 249 | 'fr-TD', 250 | 'fr-TG', 251 | 'fr-TN', 252 | 'fr-VU', 253 | 'fr-WF', 254 | 'fr-YT', 255 | 'ga', 256 | 'gl', 257 | 'gu', 258 | 'he', 259 | 'hi', 260 | 'hr', 261 | 'hr-BA', 262 | 'hu', 263 | 'hy', 264 | 'id', 265 | 'is', 266 | 'it', 267 | 'it-CH', 268 | 'it-SM', 269 | 'ja', 270 | 'ka', 271 | 'kk', 272 | 'km', 273 | 'kn', 274 | 'ko', 275 | 'ko-KP', 276 | 'ky', 277 | 'lo', 278 | 'lt', 279 | 'lv', 280 | 'mk', 281 | 'ml', 282 | 'mn', 283 | 'mr', 284 | 'ms', 285 | 'ms-BN', 286 | 'ms-SG', 287 | 'my', 288 | 'nb', 289 | 'nb-SJ', 290 | 'ne', 291 | 'ne-IN', 292 | 'nl', 293 | 'nl-AW', 294 | 'nl-BE', 295 | 'nl-BQ', 296 | 'nl-CW', 297 | 'nl-SR', 298 | 'nl-SX', 299 | 'pa', 300 | 'pa-Guru', 301 | 'pl', 302 | 'pt', 303 | 'pt-AO', 304 | 'pt-CH', 305 | 'pt-CV', 306 | 'pt-GQ', 307 | 'pt-GW', 308 | 'pt-LU', 309 | 'pt-MO', 310 | 'pt-MZ', 311 | 'pt-PT', 312 | 'pt-ST', 313 | 'pt-TL', 314 | 'ro', 315 | 'ro-MD', 316 | 'root', 317 | 'ru', 318 | 'ru-BY', 319 | 'ru-KG', 320 | 'ru-KZ', 321 | 'ru-MD', 322 | 'ru-UA', 323 | 'si', 324 | 'sk', 325 | 'sl', 326 | 'sq', 327 | 'sq-MK', 328 | 'sq-XK', 329 | 'sr', 330 | 'sr-Cyrl', 331 | 'sr-Cyrl-BA', 332 | 'sr-Cyrl-ME', 333 | 'sr-Cyrl-XK', 334 | 'sr-Latn', 335 | 'sr-Latn-BA', 336 | 'sr-Latn-ME', 337 | 'sr-Latn-XK', 338 | 'sv', 339 | 'sv-AX', 340 | 'sv-FI', 341 | 'sw', 342 | 'sw-CD', 343 | 'sw-KE', 344 | 'sw-UG', 345 | 'ta', 346 | 'ta-LK', 347 | 'ta-MY', 348 | 'ta-SG', 349 | 'te', 350 | 'th', 351 | 'to', 352 | 'tr', 353 | 'tr-CY', 354 | 'uk', 355 | 'ur', 356 | 'ur-IN', 357 | 'uz', 358 | 'uz-Latn', 359 | 'vi', 360 | 'yue', 361 | 'zh', 362 | 'zh-Hans', 363 | 'zh-Hans-CN', 364 | 'zh-Hans-HK', 365 | 'zh-Hans-MO', 366 | 'zh-Hans-SG', 367 | 'zh-Hant', 368 | 'zh-Hant-TW', 369 | 'zh-Hant-HK', 370 | 'zh-Hant-MO', 371 | 'zu' 372 | ]; 373 | -------------------------------------------------------------------------------- /src/types/locale/country.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "Afghanistan", 3 | "Albania", 4 | "Algeria", 5 | "American Samoa", 6 | "Andorra", 7 | "Angola", 8 | "Anguilla", 9 | "Antarctica (the territory South of 60 deg S)", 10 | "Antigua and Barbuda", 11 | "Argentina", 12 | "Armenia", 13 | "Aruba", 14 | "Australia", 15 | "Austria", 16 | "Azerbaijan", 17 | "Bahamas", 18 | "Bahrain", 19 | "Bangladesh", 20 | "Barbados", 21 | "Belarus", 22 | "Belgium", 23 | "Belize", 24 | "Benin", 25 | "Bermuda", 26 | "Bhutan", 27 | "Bolivia", 28 | "Bosnia and Herzegovina", 29 | "Botswana", 30 | "Bouvet Island (Bouvetoya)", 31 | "Brazil", 32 | "British Indian Ocean Territory (Chagos Archipelago)", 33 | "Brunei Darussalam", 34 | "Bulgaria", 35 | "Burkina Faso", 36 | "Burundi", 37 | "Cambodia", 38 | "Cameroon", 39 | "Canada", 40 | "Cape Verde", 41 | "Cayman Islands", 42 | "Central African Republic", 43 | "Chad", 44 | "Chile", 45 | "China", 46 | "Christmas Island", 47 | "Cocos (Keeling) Islands", 48 | "Colombia", 49 | "Comoros", 50 | "Congo", 51 | "Cook Islands", 52 | "Costa Rica", 53 | "Cote d'Ivoire", 54 | "Croatia", 55 | "Cuba", 56 | "Cyprus", 57 | "Czech Republic", 58 | "Denmark", 59 | "Djibouti", 60 | "Dominica", 61 | "Dominican Republic", 62 | "Ecuador", 63 | "Egypt", 64 | "El Salvador", 65 | "Equatorial Guinea", 66 | "Eritrea", 67 | "Estonia", 68 | "Ethiopia", 69 | "Faroe Islands", 70 | "Falkland Islands (Malvinas)", 71 | "Fiji", 72 | "Finland", 73 | "France", 74 | "French Guiana", 75 | "French Polynesia", 76 | "French Southern Territories", 77 | "Gabon", 78 | "Gambia", 79 | "Georgia", 80 | "Germany", 81 | "Ghana", 82 | "Gibraltar", 83 | "Greece", 84 | "Greenland", 85 | "Grenada", 86 | "Guadeloupe", 87 | "Guam", 88 | "Guatemala", 89 | "Guernsey", 90 | "Guinea", 91 | "Guinea-Bissau", 92 | "Guyana", 93 | "Haiti", 94 | "Heard Island and McDonald Islands", 95 | "Holy See (Vatican City State)", 96 | "Honduras", 97 | "Hong Kong", 98 | "Hungary", 99 | "Iceland", 100 | "India", 101 | "Indonesia", 102 | "Iran", 103 | "Iraq", 104 | "Ireland", 105 | "Isle of Man", 106 | "Israel", 107 | "Italy", 108 | "Jamaica", 109 | "Japan", 110 | "Jersey", 111 | "Jordan", 112 | "Kazakhstan", 113 | "Kenya", 114 | "Kiribati", 115 | "Democratic People's Republic of Korea", 116 | "Republic of Korea", 117 | "Kuwait", 118 | "Kyrgyz Republic", 119 | "Lao People's Democratic Republic", 120 | "Latvia", 121 | "Lebanon", 122 | "Lesotho", 123 | "Liberia", 124 | "Libyan Arab Jamahiriya", 125 | "Liechtenstein", 126 | "Lithuania", 127 | "Luxembourg", 128 | "Macao", 129 | "Macedonia", 130 | "Madagascar", 131 | "Malawi", 132 | "Malaysia", 133 | "Maldives", 134 | "Mali", 135 | "Malta", 136 | "Marshall Islands", 137 | "Martinique", 138 | "Mauritania", 139 | "Mauritius", 140 | "Mayotte", 141 | "Mexico", 142 | "Micronesia", 143 | "Moldova", 144 | "Monaco", 145 | "Mongolia", 146 | "Montenegro", 147 | "Montserrat", 148 | "Morocco", 149 | "Mozambique", 150 | "Myanmar", 151 | "Namibia", 152 | "Nauru", 153 | "Nepal", 154 | "Netherlands Antilles", 155 | "Netherlands", 156 | "New Caledonia", 157 | "New Zealand", 158 | "Nicaragua", 159 | "Niger", 160 | "Nigeria", 161 | "Niue", 162 | "Norfolk Island", 163 | "Northern Mariana Islands", 164 | "Norway", 165 | "Oman", 166 | "Pakistan", 167 | "Palau", 168 | "Palestinian Territory", 169 | "Panama", 170 | "Papua New Guinea", 171 | "Paraguay", 172 | "Peru", 173 | "Philippines", 174 | "Pitcairn Islands", 175 | "Poland", 176 | "Portugal", 177 | "Puerto Rico", 178 | "Qatar", 179 | "Reunion", 180 | "Romania", 181 | "Russian Federation", 182 | "Rwanda", 183 | "Saint Barthelemy", 184 | "Saint Helena", 185 | "Saint Kitts and Nevis", 186 | "Saint Lucia", 187 | "Saint Martin", 188 | "Saint Pierre and Miquelon", 189 | "Saint Vincent and the Grenadines", 190 | "Samoa", 191 | "San Marino", 192 | "Sao Tome and Principe", 193 | "Saudi Arabia", 194 | "Senegal", 195 | "Serbia", 196 | "Seychelles", 197 | "Sierra Leone", 198 | "Singapore", 199 | "Slovakia (Slovak Republic)", 200 | "Slovenia", 201 | "Solomon Islands", 202 | "Somalia", 203 | "South Africa", 204 | "South Georgia and the South Sandwich Islands", 205 | "Spain", 206 | "Sri Lanka", 207 | "Sudan", 208 | "Suriname", 209 | "Svalbard & Jan Mayen Islands", 210 | "Swaziland", 211 | "Sweden", 212 | "Switzerland", 213 | "Syrian Arab Republic", 214 | "Taiwan", 215 | "Tajikistan", 216 | "Tanzania", 217 | "Thailand", 218 | "Timor-Leste", 219 | "Togo", 220 | "Tokelau", 221 | "Tonga", 222 | "Trinidad and Tobago", 223 | "Tunisia", 224 | "Turkey", 225 | "Turkmenistan", 226 | "Turks and Caicos Islands", 227 | "Tuvalu", 228 | "Uganda", 229 | "Ukraine", 230 | "United Arab Emirates", 231 | "United Kingdom", 232 | "United States of America", 233 | "United States Minor Outlying Islands", 234 | "Uruguay", 235 | "Uzbekistan", 236 | "Vanuatu", 237 | "Venezuela", 238 | "Vietnam", 239 | "Virgin Islands, British", 240 | "Virgin Islands, U.S.", 241 | "Wallis and Futuna", 242 | "Western Sahara", 243 | "Yemen", 244 | "Zambia", 245 | "Zimbabwe" 246 | ]; 247 | -------------------------------------------------------------------------------- /src/types/locale/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | import { Arbitrary } from '../../arbitrary'; 5 | import { elements } from '../../combinators'; 6 | import avaliableLocaleIds from './avaliableLocaleids'; 7 | import timeZone from './timeZone'; 8 | import _country from './country'; 9 | 10 | /** 11 | * Available Locale Ids in Unicode Common Locale Data Repository. 12 | * 13 | * @example 14 | * // returns zh-Hant-TW 15 | * ke.locale.localeids.generate(); 16 | */ 17 | const localeId = elements(avaliableLocaleIds).set('name', 'Locale Id'); 18 | 19 | /** 20 | * Time Zone 21 | */ 22 | const timezone = elements(timeZone).set('name', 'Time Zone'); 23 | 24 | /** 25 | * Country 26 | */ 27 | const country = elements(_country).set('name', 'Country'); 28 | 29 | export const locale = { 30 | avaliableLocaleIds, 31 | localeId, 32 | country, 33 | timezone 34 | }; 35 | -------------------------------------------------------------------------------- /src/types/locale/timeZone.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "Pacific/Midway", 3 | "Pacific/Pago_Pago", 4 | "Pacific/Honolulu", 5 | "America/Juneau", 6 | "America/Los_Angeles", 7 | "America/Tijuana", 8 | "America/Denver", 9 | "America/Phoenix", 10 | "America/Chihuahua", 11 | "America/Mazatlan", 12 | "America/Chicago", 13 | "America/Regina", 14 | "America/Mexico_City", 15 | "America/Mexico_City", 16 | "America/Monterrey", 17 | "America/Guatemala", 18 | "America/New_York", 19 | "America/Indiana/Indianapolis", 20 | "America/Bogota", 21 | "America/Lima", 22 | "America/Lima", 23 | "America/Halifax", 24 | "America/Caracas", 25 | "America/La_Paz", 26 | "America/Santiago", 27 | "America/St_Johns", 28 | "America/Sao_Paulo", 29 | "America/Argentina/Buenos_Aires", 30 | "America/Guyana", 31 | "America/Godthab", 32 | "Atlantic/South_Georgia", 33 | "Atlantic/Azores", 34 | "Atlantic/Cape_Verde", 35 | "Europe/Dublin", 36 | "Europe/London", 37 | "Europe/Lisbon", 38 | "Europe/London", 39 | "Africa/Casablanca", 40 | "Africa/Monrovia", 41 | "Etc/UTC", 42 | "Europe/Belgrade", 43 | "Europe/Bratislava", 44 | "Europe/Budapest", 45 | "Europe/Ljubljana", 46 | "Europe/Prague", 47 | "Europe/Sarajevo", 48 | "Europe/Skopje", 49 | "Europe/Warsaw", 50 | "Europe/Zagreb", 51 | "Europe/Brussels", 52 | "Europe/Copenhagen", 53 | "Europe/Madrid", 54 | "Europe/Paris", 55 | "Europe/Amsterdam", 56 | "Europe/Berlin", 57 | "Europe/Berlin", 58 | "Europe/Rome", 59 | "Europe/Stockholm", 60 | "Europe/Vienna", 61 | "Africa/Algiers", 62 | "Europe/Bucharest", 63 | "Africa/Cairo", 64 | "Europe/Helsinki", 65 | "Europe/Kiev", 66 | "Europe/Riga", 67 | "Europe/Sofia", 68 | "Europe/Tallinn", 69 | "Europe/Vilnius", 70 | "Europe/Athens", 71 | "Europe/Istanbul", 72 | "Europe/Minsk", 73 | "Asia/Jerusalem", 74 | "Africa/Harare", 75 | "Africa/Johannesburg", 76 | "Europe/Moscow", 77 | "Europe/Moscow", 78 | "Europe/Moscow", 79 | "Asia/Kuwait", 80 | "Asia/Riyadh", 81 | "Africa/Nairobi", 82 | "Asia/Baghdad", 83 | "Asia/Tehran", 84 | "Asia/Muscat", 85 | "Asia/Muscat", 86 | "Asia/Baku", 87 | "Asia/Tbilisi", 88 | "Asia/Yerevan", 89 | "Asia/Kabul", 90 | "Asia/Yekaterinburg", 91 | "Asia/Karachi", 92 | "Asia/Karachi", 93 | "Asia/Tashkent", 94 | "Asia/Kolkata", 95 | "Asia/Kolkata", 96 | "Asia/Kolkata", 97 | "Asia/Kolkata", 98 | "Asia/Kathmandu", 99 | "Asia/Dhaka", 100 | "Asia/Dhaka", 101 | "Asia/Colombo", 102 | "Asia/Almaty", 103 | "Asia/Novosibirsk", 104 | "Asia/Rangoon", 105 | "Asia/Bangkok", 106 | "Asia/Bangkok", 107 | "Asia/Jakarta", 108 | "Asia/Krasnoyarsk", 109 | "Asia/Shanghai", 110 | "Asia/Chongqing", 111 | "Asia/Hong_Kong", 112 | "Asia/Urumqi", 113 | "Asia/Kuala_Lumpur", 114 | "Asia/Singapore", 115 | "Asia/Taipei", 116 | "Australia/Perth", 117 | "Asia/Irkutsk", 118 | "Asia/Ulaanbaatar", 119 | "Asia/Seoul", 120 | "Asia/Tokyo", 121 | "Asia/Tokyo", 122 | "Asia/Tokyo", 123 | "Asia/Yakutsk", 124 | "Australia/Darwin", 125 | "Australia/Adelaide", 126 | "Australia/Melbourne", 127 | "Australia/Melbourne", 128 | "Australia/Sydney", 129 | "Australia/Brisbane", 130 | "Australia/Hobart", 131 | "Asia/Vladivostok", 132 | "Pacific/Guam", 133 | "Pacific/Port_Moresby", 134 | "Asia/Magadan", 135 | "Asia/Magadan", 136 | "Pacific/Noumea", 137 | "Pacific/Fiji", 138 | "Asia/Kamchatka", 139 | "Pacific/Majuro", 140 | "Pacific/Auckland", 141 | "Pacific/Auckland", 142 | "Pacific/Tongatapu", 143 | "Pacific/Fakaofo", 144 | "Pacific/Apia" 145 | ]; 146 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/address.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | '${streetAddress}, ${city}, ${state}, ${zipCode}' 3 | ] 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/buildingNumber.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | /[0-9]{3,5}/, 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/city.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "${prefix} ${firstName}${suffix}", 3 | "${prefix} ${firstName}", 4 | "${firstName}${suffix}", 5 | "${lastName}${suffix}" 6 | ]; 7 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/cityPrefix.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "North", 3 | "East", 4 | "West", 5 | "South", 6 | "New", 7 | "Lake", 8 | "Port" 9 | ]; 10 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/citySuffix.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "town", 3 | "ton", 4 | "land", 5 | "ville", 6 | "berg", 7 | "burgh", 8 | "borough", 9 | "bury", 10 | "view", 11 | "port", 12 | "mouth", 13 | "stad", 14 | "furt", 15 | "chester", 16 | "mouth", 17 | "fort", 18 | "haven", 19 | "side", 20 | "shire" 21 | ]; 22 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/county.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "Avon", 3 | "Bedfordshire", 4 | "Berkshire", 5 | "Borders", 6 | "Buckinghamshire", 7 | "Cambridgeshire" 8 | ]; 9 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/index.ts: -------------------------------------------------------------------------------- 1 | export {default as city} from './city'; 2 | export {default as cityPrefix} from './cityPrefix'; 3 | export {default as citySuffix} from './citySuffix'; 4 | export {default as county} from './county'; 5 | export {default as buildingNumber} from './buildingNumber'; 6 | export {default as streetSuffix} from './streetSuffix'; 7 | export {default as secondaryAddress} from './secondaryAddress'; 8 | export {default as postcode} from './postcode'; 9 | export {default as state} from './state'; 10 | export {default as street } from './street'; 11 | export {default as stateAbbr} from './stateAbbr'; 12 | export {default as address} from './address'; 13 | export {default as streetAddress} from './streetAddress'; 14 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/postcode.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | /[0-9]{5}/, 3 | /[0-9]{5}-[0-9]{3}/ 4 | ]; 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/secondaryAddress.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | /(Apt\.|Suite) [0-9]{3}/, 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/state.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "Alabama", 3 | "Alaska", 4 | "Arizona", 5 | "Arkansas", 6 | "California", 7 | "Colorado", 8 | "Connecticut", 9 | "Delaware", 10 | "Florida", 11 | "Georgia", 12 | "Hawaii", 13 | "Idaho", 14 | "Illinois", 15 | "Indiana", 16 | "Iowa", 17 | "Kansas", 18 | "Kentucky", 19 | "Louisiana", 20 | "Maine", 21 | "Maryland", 22 | "Massachusetts", 23 | "Michigan", 24 | "Minnesota", 25 | "Mississippi", 26 | "Missouri", 27 | "Montana", 28 | "Nebraska", 29 | "Nevada", 30 | "New Hampshire", 31 | "New Jersey", 32 | "New Mexico", 33 | "New York", 34 | "North Carolina", 35 | "North Dakota", 36 | "Ohio", 37 | "Oklahoma", 38 | "Oregon", 39 | "Pennsylvania", 40 | "Rhode Island", 41 | "South Carolina", 42 | "South Dakota", 43 | "Tennessee", 44 | "Texas", 45 | "Utah", 46 | "Vermont", 47 | "Virginia", 48 | "Washington", 49 | "West Virginia", 50 | "Wisconsin", 51 | "Wyoming" 52 | ]; 53 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/stateAbbr.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "AL", 3 | "AK", 4 | "AZ", 5 | "AR", 6 | "CA", 7 | "CO", 8 | "CT", 9 | "DE", 10 | "FL", 11 | "GA", 12 | "HI", 13 | "ID", 14 | "IL", 15 | "IN", 16 | "IA", 17 | "KS", 18 | "KY", 19 | "LA", 20 | "ME", 21 | "MD", 22 | "MA", 23 | "MI", 24 | "MN", 25 | "MS", 26 | "MO", 27 | "MT", 28 | "NE", 29 | "NV", 30 | "NH", 31 | "NJ", 32 | "NM", 33 | "NY", 34 | "NC", 35 | "ND", 36 | "OH", 37 | "OK", 38 | "OR", 39 | "PA", 40 | "RI", 41 | "SC", 42 | "SD", 43 | "TN", 44 | "TX", 45 | "UT", 46 | "VT", 47 | "VA", 48 | "WA", 49 | "WV", 50 | "WI", 51 | "WY" 52 | ]; 53 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/street.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | '${firstName} ${suffix}', 3 | '${lastName} ${suffix}' 4 | ] 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/streetAddress.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | '${buildingNumber}, ${street}', 3 | '${buildingNumber}, ${street}, ${secondaryAddress}', 4 | ] 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/en/streetSuffix.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "Alley", 3 | "Avenue", 4 | "Branch", 5 | "Bridge", 6 | "Brook", 7 | "Brooks", 8 | "Burg", 9 | "Burgs", 10 | "Bypass", 11 | "Camp", 12 | "Canyon", 13 | "Cape", 14 | "Causeway", 15 | "Center", 16 | "Centers", 17 | "Circle", 18 | "Circles", 19 | "Cliff", 20 | "Cliffs", 21 | "Club", 22 | "Common", 23 | "Corner", 24 | "Corners", 25 | "Course", 26 | "Court", 27 | "Courts", 28 | "Cove", 29 | "Coves", 30 | "Creek", 31 | "Crescent", 32 | "Crest", 33 | "Crossing", 34 | "Crossroad", 35 | "Curve", 36 | "Dale", 37 | "Dam", 38 | "Divide", 39 | "Drive", 40 | "Drive", 41 | "Drives", 42 | "Estate", 43 | "Estates", 44 | "Expressway", 45 | "Extension", 46 | "Extensions", 47 | "Fall", 48 | "Falls", 49 | "Ferry", 50 | "Field", 51 | "Fields", 52 | "Flat", 53 | "Flats", 54 | "Ford", 55 | "Fords", 56 | "Forest", 57 | "Forge", 58 | "Forges", 59 | "Fork", 60 | "Forks", 61 | "Fort", 62 | "Freeway", 63 | "Garden", 64 | "Gardens", 65 | "Gateway", 66 | "Glen", 67 | "Glens", 68 | "Green", 69 | "Greens", 70 | "Grove", 71 | "Groves", 72 | "Harbor", 73 | "Harbors", 74 | "Haven", 75 | "Heights", 76 | "Highway", 77 | "Hill", 78 | "Hills", 79 | "Hollow", 80 | "Inlet", 81 | "Inlet", 82 | "Island", 83 | "Island", 84 | "Islands", 85 | "Islands", 86 | "Isle", 87 | "Isle", 88 | "Junction", 89 | "Junctions", 90 | "Key", 91 | "Keys", 92 | "Knoll", 93 | "Knolls", 94 | "Lake", 95 | "Lakes", 96 | "Land", 97 | "Landing", 98 | "Lane", 99 | "Light", 100 | "Lights", 101 | "Loaf", 102 | "Lock", 103 | "Locks", 104 | "Locks", 105 | "Lodge", 106 | "Lodge", 107 | "Loop", 108 | "Mall", 109 | "Manor", 110 | "Manors", 111 | "Meadow", 112 | "Meadows", 113 | "Mews", 114 | "Mill", 115 | "Mills", 116 | "Mission", 117 | "Mission", 118 | "Motorway", 119 | "Mount", 120 | "Mountain", 121 | "Mountain", 122 | "Mountains", 123 | "Mountains", 124 | "Neck", 125 | "Orchard", 126 | "Oval", 127 | "Overpass", 128 | "Park", 129 | "Parks", 130 | "Parkway", 131 | "Parkways", 132 | "Pass", 133 | "Passage", 134 | "Path", 135 | "Pike", 136 | "Pine", 137 | "Pines", 138 | "Place", 139 | "Plain", 140 | "Plains", 141 | "Plains", 142 | "Plaza", 143 | "Plaza", 144 | "Point", 145 | "Points", 146 | "Port", 147 | "Port", 148 | "Ports", 149 | "Ports", 150 | "Prairie", 151 | "Prairie", 152 | "Radial", 153 | "Ramp", 154 | "Ranch", 155 | "Rapid", 156 | "Rapids", 157 | "Rest", 158 | "Ridge", 159 | "Ridges", 160 | "River", 161 | "Road", 162 | "Road", 163 | "Roads", 164 | "Roads", 165 | "Route", 166 | "Row", 167 | "Rue", 168 | "Run", 169 | "Shoal", 170 | "Shoals", 171 | "Shore", 172 | "Shores", 173 | "Skyway", 174 | "Spring", 175 | "Springs", 176 | "Springs", 177 | "Spur", 178 | "Spurs", 179 | "Square", 180 | "Square", 181 | "Squares", 182 | "Squares", 183 | "Station", 184 | "Station", 185 | "Stravenue", 186 | "Stravenue", 187 | "Stream", 188 | "Stream", 189 | "Street", 190 | "Street", 191 | "Streets", 192 | "Summit", 193 | "Summit", 194 | "Terrace", 195 | "Throughway", 196 | "Trace", 197 | "Track", 198 | "Trafficway", 199 | "Trail", 200 | "Trail", 201 | "Tunnel", 202 | "Tunnel", 203 | "Turnpike", 204 | "Turnpike", 205 | "Underpass", 206 | "Union", 207 | "Unions", 208 | "Valley", 209 | "Valleys", 210 | "Via", 211 | "Viaduct", 212 | "View", 213 | "Views", 214 | "Village", 215 | "Village", 216 | "Villages", 217 | "Ville", 218 | "Vista", 219 | "Vista", 220 | "Walk", 221 | "Walks", 222 | "Wall", 223 | "Way", 224 | "Ways", 225 | "Well", 226 | "Wells" 227 | ]; 228 | -------------------------------------------------------------------------------- /src/types/location/definitions/index.ts: -------------------------------------------------------------------------------- 1 | import * as en from './en/index'; 2 | import * as zh_Hant_TW from './zh-Hant-TW/index'; 3 | 4 | export default { 5 | en, 6 | zh_Hant_TW 7 | }; 8 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/address.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | '${streetAddress}, ${city}, ${state}, ${zipCode}', 3 | '${streetAddress}, ${city}, ${county}, ${state}, ${zipCode}' 4 | ] 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/buildingNumber.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | /[0-9]{1,4}/ 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/city.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | '${prefix}市' 3 | ] 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/cityPrefix.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "臺北", 3 | "新北", 4 | "桃園", 5 | "臺中", 6 | "臺南", 7 | "高雄", 8 | "基隆", 9 | "新竹", 10 | "嘉義", 11 | "苗栗", 12 | "彰化", 13 | "南投", 14 | "雲林", 15 | "屏東", 16 | "宜蘭", 17 | "花蓮", 18 | "臺東", 19 | "澎湖", 20 | "金門", 21 | "連江" 22 | ]; 23 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/citySuffix.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "縣", 3 | "市" 4 | ]; 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/county.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | '新竹縣', 3 | '苗栗縣', 4 | '彰化縣', 5 | '南投縣', 6 | '雲林縣', 7 | '嘉義縣', 8 | '屏東縣', 9 | '宜蘭縣', 10 | '花蓮縣', 11 | '臺東縣', 12 | '澎湖縣', 13 | '金門縣', 14 | '連江縣' 15 | ] 16 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/index.ts: -------------------------------------------------------------------------------- 1 | export {default as city} from './city'; 2 | export {default as cityPrefix} from './cityPrefix'; 3 | export {default as citySuffix} from './citySuffix'; 4 | export {default as county} from './county'; 5 | export {default as buildingNumber} from './buildingNumber'; 6 | export {default as streetSuffix} from './streetSuffix'; 7 | export {default as postcode} from './postcode'; 8 | export {default as state} from './state'; 9 | export {default as street } from './street'; 10 | export {default as stateAbbr} from './stateAbbr'; 11 | export {default as address} from './address'; 12 | export {default as secondaryAddress} from './secondaryAddress'; 13 | export {default as streetAddress} from './streetAddress'; 14 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/postcode.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | /[0-9]{6}/ 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/secondaryAddress.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | /(新莊|中和|板橋)(鄉|區|鎮)/ 3 | ] 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/state.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "福建省", 3 | "台灣省" 4 | ]; 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/stateAbbr.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "北", 3 | "新北", 4 | "桃", 5 | "中", 6 | "南", 7 | "高", 8 | "基", 9 | "竹市", 10 | "嘉市", 11 | "竹縣", 12 | "苗", 13 | "彰", 14 | "投", 15 | "雲", 16 | "嘉縣", 17 | "宜", 18 | "花", 19 | "東", 20 | "澎", 21 | "金", 22 | "馬" 23 | ]; 24 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/street.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "${lastName}${suffix}" 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/streetAddress.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "${street}${buildingNumber}號", 3 | "${street}${buildingNumber}號, ${secondaryAddress}" 4 | ]; 5 | -------------------------------------------------------------------------------- /src/types/location/definitions/zh-Hant-TW/streetSuffix.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | "街", 3 | "路", 4 | "北路", 5 | "南路", 6 | "東路", 7 | "西路" 8 | ]; 9 | -------------------------------------------------------------------------------- /src/types/location/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module 3 | */ 4 | import { Arbitrary } from '../../arbitrary'; 5 | import { object, constant } from '../../combinators'; 6 | import { num, NumberGenOpts } from '../primitive/index'; 7 | import { person } from '../person/index'; 8 | 9 | import { Definitions } from '../../definition'; 10 | 11 | import definitions from './definitions/index'; 12 | const defs = new Definitions(definitions); 13 | 14 | /** 15 | * State 16 | * @example 17 | * // returns Alabama 18 | * ke.location.state.random 19 | */ 20 | const state = defs.arbitrary('state').set('name', 'State'); 21 | 22 | /** 23 | * State Abbr. 24 | * @example 25 | * // returns AL 26 | * ke.location.state.abbr.random 27 | */ 28 | state.assign({ 29 | abbr: defs.arbitrary('stateAbbr').set('name', 'State Abbr') 30 | }); 31 | 32 | /** 33 | * Zip Code 34 | */ 35 | const zipCode = defs.arbitrary('postcode').set('name', 'Zip Code'); 36 | 37 | /** 38 | * County 39 | * @example 40 | * // returns Avon 41 | * ke.location.county.random 42 | */ 43 | const county = defs.arbitrary('county').set('name', 'County'); 44 | 45 | const cityPrefix = defs.arbitrary('cityPrefix'); 46 | const citySuffix = defs.arbitrary('citySuffix'); 47 | 48 | /** 49 | * City 50 | * @example 51 | * // returns Port Sammybury 52 | * ke.location.city.random 53 | */ 54 | const city = object({ 55 | firstName: person.firstName, 56 | lastName: person.lastName, 57 | suffix: citySuffix, 58 | prefix: cityPrefix 59 | }).transform(defs.formatter('city')).set('name', 'City'); 60 | 61 | /** 62 | * Street 63 | */ 64 | const street = object({ 65 | firstName: person.firstName, 66 | lastName: person.lastName, 67 | suffix: defs.arbitrary('streetSuffix') 68 | }).transform(defs.formatter('street')).set('name', 'Street'); 69 | 70 | /** 71 | * Building Number 72 | */ 73 | const buildingNumber = defs.arbitrary('buildingNumber'); 74 | 75 | const streetAddress = object({ 76 | street: street, 77 | buildingNumber: buildingNumber, 78 | secondaryAddress: defs.arbitrary('secondaryAddress') 79 | }).transform(defs.formatter('streetAddress')).set('name', 'Street Address'); 80 | 81 | /** 82 | * Address 83 | */ 84 | const address = object({ 85 | streetAddress: streetAddress, 86 | state: state, 87 | county: county, 88 | city: city, 89 | zipCode: zipCode 90 | }).transform(defs.formatter('address')).set('name', 'Address'); 91 | 92 | /** 93 | * latitude 94 | * @example 95 | * // returns 19.4984. 96 | * ke.location.latitude.random 97 | */ 98 | const latitude = num.choose({ min: 0, max: 180 * 10000 }) 99 | .transform(n => (n / 10000.0 - 90.0).toFixed(4)); 100 | 101 | /** 102 | * longitude 103 | * @example 104 | * // returns 132.9634. 105 | * ke.location.longitude.random 106 | */ 107 | const longitude = num.choose({ min: 0, max: 360 * 10000 }) 108 | .transform(n => (n / 10000.0 - 180.0).toFixed(4)); 109 | 110 | /** 111 | * coordinates 112 | * @example 113 | * // returns 19.4984, 132.9634. 114 | * ke.location.coordinates.random 115 | */ 116 | const coordinates = object({ 117 | latitude: latitude, 118 | longitude: longitude 119 | }).transform(c => `${c.latitude}, ${c.longtitude}`) 120 | .set('name', 'Coordinate'); 121 | 122 | export const location = { 123 | address, 124 | streetAddress, 125 | state, 126 | zipCode, 127 | county, 128 | city, 129 | street, 130 | buildingNumber, 131 | latitude, 132 | longitude, 133 | coordinates 134 | } 135 | -------------------------------------------------------------------------------- /src/types/person/definitions/en/gender.ts: -------------------------------------------------------------------------------- 1 | export const gender = [ 2 | 'Male', 'Female' 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/person/definitions/en/index.ts: -------------------------------------------------------------------------------- 1 | export * from './name'; 2 | export * from './firstName'; 3 | export * from './lastName'; 4 | export * from './gender'; 5 | -------------------------------------------------------------------------------- /src/types/person/definitions/en/name.ts: -------------------------------------------------------------------------------- 1 | export function name(name: any) { 2 | return `${name.firstName} ${name.lastName}`; 3 | }; 4 | -------------------------------------------------------------------------------- /src/types/person/definitions/index.ts: -------------------------------------------------------------------------------- 1 | import * as en from './en/index'; 2 | import * as zh_Hant_TW from './zh-Hant-TW/index'; 3 | 4 | export default { 5 | en, 6 | zh_Hant_TW 7 | }; 8 | -------------------------------------------------------------------------------- /src/types/person/definitions/zh-Hant-TW/firstName.ts: -------------------------------------------------------------------------------- 1 | export const firstName = [ 2 | "王", 3 | "李", 4 | "張", 5 | "劉", 6 | "陳", 7 | "楊", 8 | "黃", 9 | "吳", 10 | "趙", 11 | "週", 12 | "徐", 13 | "孫", 14 | "馬", 15 | "朱", 16 | "胡", 17 | "林", 18 | "郭", 19 | "何", 20 | "高", 21 | "羅", 22 | "鄭", 23 | "梁", 24 | "謝", 25 | "宋", 26 | "唐", 27 | "許", 28 | "鄧", 29 | "馮", 30 | "韓", 31 | "曹", 32 | "曾", 33 | "彭", 34 | "蕭", 35 | "蔡", 36 | "潘", 37 | "田", 38 | "董", 39 | "袁", 40 | "於", 41 | "餘", 42 | "葉", 43 | "蔣", 44 | "杜", 45 | "蘇", 46 | "魏", 47 | "程", 48 | "呂", 49 | "丁", 50 | "沈", 51 | "任", 52 | "姚", 53 | "盧", 54 | "傅", 55 | "鐘", 56 | "姜", 57 | "崔", 58 | "譚", 59 | "廖", 60 | "範", 61 | "汪", 62 | "陸", 63 | "金", 64 | "石", 65 | "戴", 66 | "賈", 67 | "韋", 68 | "夏", 69 | "邱", 70 | "方", 71 | "侯", 72 | "鄒", 73 | "熊", 74 | "孟", 75 | "秦", 76 | "白", 77 | "江", 78 | "閻", 79 | "薛", 80 | "尹", 81 | "段", 82 | "雷", 83 | "黎", 84 | "史", 85 | "龍", 86 | "陶", 87 | "賀", 88 | "顧", 89 | "毛", 90 | "郝", 91 | "龔", 92 | "邵", 93 | "萬", 94 | "錢", 95 | "嚴", 96 | "賴", 97 | "覃", 98 | "洪", 99 | "武", 100 | "莫", 101 | "孔" 102 | ]; 103 | -------------------------------------------------------------------------------- /src/types/person/definitions/zh-Hant-TW/gender.ts: -------------------------------------------------------------------------------- 1 | export const gender = [ 2 | '男', '女' 3 | ]; 4 | -------------------------------------------------------------------------------- /src/types/person/definitions/zh-Hant-TW/index.ts: -------------------------------------------------------------------------------- 1 | export * from './name'; 2 | export * from './gender'; 3 | export * from './firstName'; 4 | export * from './lastName'; 5 | -------------------------------------------------------------------------------- /src/types/person/definitions/zh-Hant-TW/lastName.ts: -------------------------------------------------------------------------------- 1 | export const lastName =[ 2 | '紹齊', 3 | '博文', 4 | '梓晨', 5 | '胤祥', 6 | '瑞霖', 7 | '明哲', 8 | '天翊', 9 | '凱瑞', 10 | '健雄', 11 | '耀傑', 12 | '瀟然', 13 | '子涵', 14 | '越彬', 15 | '鈺軒', 16 | '智輝', 17 | '致遠', 18 | '俊馳', 19 | '雨澤', 20 | '燁磊', 21 | '晟睿', 22 | '文昊', 23 | '修潔', 24 | '黎昕', 25 | '遠航', 26 | '旭堯', 27 | '鴻濤', 28 | '偉祺', 29 | '榮軒', 30 | '越澤', 31 | '浩宇', 32 | '瑾瑜', 33 | '皓軒', 34 | '擎蒼', 35 | '擎宇', 36 | '志澤', 37 | '子軒', 38 | '睿淵', 39 | '弘文', 40 | '哲瀚', 41 | '雨澤', 42 | '楷瑞', 43 | '建輝', 44 | '晉鵬', 45 | '天磊', 46 | '紹輝', 47 | '澤洋', 48 | '鑫磊', 49 | '鵬煊', 50 | '昊強', 51 | '偉宸', 52 | '博超', 53 | '君浩', 54 | '子騫', 55 | '鵬濤', 56 | '炎彬', 57 | '鶴軒', 58 | '越彬', 59 | '風華', 60 | '靖琪', 61 | '明輝', 62 | '偉誠', 63 | '明軒', 64 | '健柏', 65 | '修傑', 66 | '志澤', 67 | '弘文', 68 | '峻熙', 69 | '嘉懿', 70 | '煜城', 71 | '懿軒', 72 | '燁偉', 73 | '苑博', 74 | '偉澤', 75 | '熠彤', 76 | '鴻煊', 77 | '博濤', 78 | '燁霖', 79 | '燁華', 80 | '煜祺', 81 | '智宸', 82 | '正豪', 83 | '昊然', 84 | '明杰', 85 | '立誠', 86 | '立軒', 87 | '立輝', 88 | '峻熙', 89 | '弘文', 90 | '熠彤', 91 | '鴻煊', 92 | '燁霖', 93 | '哲瀚', 94 | '鑫鵬', 95 | '昊天', 96 | '思聰', 97 | '展鵬', 98 | '笑愚', 99 | '志強', 100 | '炫明', 101 | '雪松', 102 | '思源', 103 | '智淵', 104 | '思淼', 105 | '曉嘯', 106 | '天宇', 107 | '浩然', 108 | '文軒', 109 | '鷺洋', 110 | '振家', 111 | '樂駒', 112 | '曉博', 113 | '文博', 114 | '昊焱', 115 | '立果', 116 | '金鑫', 117 | '錦程', 118 | '嘉熙', 119 | '鵬飛', 120 | '子默', 121 | '思遠', 122 | '浩軒', 123 | '語堂', 124 | '聰健' 125 | ]; 126 | -------------------------------------------------------------------------------- /src/types/person/definitions/zh-Hant-TW/name.ts: -------------------------------------------------------------------------------- 1 | export function name(name: any) { 2 | return `${name.firstName}${name.lastName}`; 3 | } 4 | -------------------------------------------------------------------------------- /src/types/person/index.ts: -------------------------------------------------------------------------------- 1 | import { Arbitrary} from '../../arbitrary'; 2 | import {object, oneOf, constant} from '../../combinators'; 3 | import {date} from '../primitive/datetime'; 4 | import {Definitions} from '../../definition'; 5 | 6 | import defsdata from './definitions/index'; 7 | const defs = new Definitions(defsdata); 8 | 9 | /** 10 | * Arbitrary to generate the first name of a person. 11 | * @example 12 | * // returns Jack. 13 | * ke.person.firstName.generate(); 14 | */ 15 | const firstName = defs.arbitrary('firstName').set('name', 'First Name'); 16 | 17 | /** 18 | * Arbitrary to generate the last name of a person. 19 | * @example 20 | * // returns Hand. 21 | * ke.person.lastName.generate(); 22 | */ 23 | const lastName = defs.arbitrary('lastName').set('name', 'Last Name'); 24 | 25 | /** 26 | * Arbitrary to generate the name of a person. 27 | * @example 28 | * ke.person.name.generate(); 29 | */ 30 | const name = object({ 31 | firstName: firstName, 32 | lastName: lastName 33 | }).transform(defs.formatter('name')) 34 | .set('name', 'Name'); 35 | 36 | /** 37 | * Arbitrary to generate the gender of a person. 38 | * @example 39 | * ke.person.gender.generate; 40 | */ 41 | const gender = defs.arbitrary('gender').set('name', 'Gender'); 42 | 43 | /** 44 | * Arbitrary to generate a person (alive, dead, undead, or fictional). 45 | * @example 46 | * // generate a object include person name, gender and birthday. 47 | * ke.person.generate(); 48 | */ 49 | export const person = object({ 50 | name: name, 51 | gender: gender, 52 | birthDay: date 53 | }).set('name', 'Person').assign({ 54 | name, 55 | firstName, 56 | lastName, 57 | gender 58 | }); -------------------------------------------------------------------------------- /src/types/primitive/any.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { any } from './any'; 3 | 4 | describe('Arbitrary Any', () => { 5 | it('name is Any', () => { 6 | expect(any.get('name')).eq('Any'); 7 | }); 8 | it('generate one of boolean, falsy, integer, number.', () => { 9 | const x = any.random; 10 | expect(typeof x === 'number' || 11 | typeof x === 'boolean' || 12 | typeof x === 'string' || 13 | x === null || 14 | x === undefined || 15 | x === void (0)).eq(true); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /src/types/primitive/any.ts: -------------------------------------------------------------------------------- 1 | import { bool } from './boolean'; 2 | import { falsy } from './falsy'; 3 | import { int, num } from './number'; 4 | import { Arbitrary } from '../../arbitrary'; 5 | import { oneOf } from '../../combinators/pickers'; 6 | 7 | /** 8 | * Arbitrary Any Primitive Type 9 | */ 10 | export const any = oneOf([ 11 | bool, falsy, int, num 12 | ]).set('name', 'Any'); -------------------------------------------------------------------------------- /src/types/primitive/boolean.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { bool } from './boolean'; 3 | 4 | describe('Arbitrary Boolean', () => { 5 | describe('#random', () => { 6 | it('produces true or false', () => { 7 | expect(typeof bool.random === 'boolean').eq(true); 8 | }); 9 | it('always produce true if chance is 100', () => { 10 | expect(bool.choose(100).random).eq(true); 11 | }); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /src/types/primitive/boolean.ts: -------------------------------------------------------------------------------- 1 | import { bool as randomBool } from 'random-js'; 2 | import { Arbitrary } from '../../arbitrary'; 3 | 4 | /** 5 | * The chance of produced value is true. from 0 to 100. 6 | */ 7 | type BooleanGenOpts = number; 8 | 9 | /** 10 | * Boolean Arbitrary 11 | * 12 | * produce true and false with equal probability. 13 | */ 14 | export const bool = new Arbitrary({ 15 | gen: randomBool 16 | }).set('name', 'Boolean'); -------------------------------------------------------------------------------- /src/types/primitive/datetime.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { isDate } from 'lodash'; 3 | import { date } from './datetime'; 4 | 5 | describe('Arbitrary Datetime', () => { 6 | describe('Date', () => { 7 | it('name is Date', () => { 8 | expect(date.get('name')).eq('Date'); 9 | }); 10 | it('should return date.', () => { 11 | const d = date.random; 12 | return isDate(d); 13 | }); 14 | it('takes two date for range.', () => { 15 | const d1 = new Date(1999, 1, 1); 16 | const d2 = new Date(2000, 3, 22); 17 | const d3 = date.choose({ start: d1, end: d2 }).random; 18 | const inRange = () => { 19 | const t1 = d1.getTime(); 20 | const t2 = d2.getTime(); 21 | const t3 = d3.getTime(); 22 | return t1 <= t3 && t3 <= t2; 23 | }; 24 | return isDate(d3) && inRange(); 25 | }); 26 | }); 27 | }); -------------------------------------------------------------------------------- /src/types/primitive/datetime.ts: -------------------------------------------------------------------------------- 1 | import { date as randomDate } from 'random-js'; 2 | import { Arbitrary } from '../../arbitrary'; 3 | 4 | /** 5 | * Options of dateGen 6 | */ 7 | export type DateGenOpts = { 8 | start: Date, 9 | end: Date 10 | } 11 | 12 | /** 13 | * Date Generator Maker. 14 | */ 15 | function dateGen({start, end}: DateGenOpts) { 16 | return randomDate(start, end); 17 | }; 18 | 19 | /** 20 | * Default Options of Date Generator Maker. 21 | */ 22 | const defaultDateGenOpts: DateGenOpts = { 23 | start: new Date(1984, 3, 25), 24 | end: new Date() 25 | } 26 | 27 | /** 28 | * Date Arbitrary 29 | */ 30 | export const date = new Arbitrary({ 31 | gen: dateGen, 32 | genOpts: defaultDateGenOpts 33 | }).set('name', 'Date'); -------------------------------------------------------------------------------- /src/types/primitive/falsy.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { falsy } from './falsy'; 3 | 4 | describe('Arbitrary Falsy', () => { 5 | it('name is Falsy', () => { 6 | expect(falsy.get('name')).eq('Falsy'); 7 | }); 8 | it('generate falsy values.', () => { 9 | const x = falsy.generate(); 10 | expect(!x).eq(true); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/types/primitive/falsy.ts: -------------------------------------------------------------------------------- 1 | import { Arbitrary } from '../../arbitrary'; 2 | import { elements } from '../../combinators/pickers'; 3 | 4 | /** 5 | * falsy values. 6 | */ 7 | export const FALSY_VALUES = [ 8 | undefined, 9 | void(0), 10 | null, 11 | false, 12 | 0, 13 | '' 14 | ]; 15 | 16 | /** 17 | * Falsy Arbitrary 18 | * 19 | * generates falsy values: false, null, undefined, '', 20 | * 0, void(0) and NaN. 21 | */ 22 | export const falsy = elements(FALSY_VALUES).set('name', 'Falsy'); 23 | -------------------------------------------------------------------------------- /src/types/primitive/index.ts: -------------------------------------------------------------------------------- 1 | export * from './any'; 2 | export * from './boolean'; 3 | export * from './number'; 4 | export * from './string'; 5 | export * from './datetime'; -------------------------------------------------------------------------------- /src/types/primitive/number.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { isNumber, isInteger, isString } from 'lodash'; 3 | import * as number from './number'; 4 | 5 | describe('Arbitrary Number', () => { 6 | describe('Integer', () => { 7 | describe('#small()', () => { 8 | it('returns small size of current arbitrary', () => { 9 | const smallInt = number.int.small; 10 | expect(smallInt.genOpts).eql({ 11 | min: -53, 12 | max: 53 13 | }); 14 | }); 15 | }); 16 | describe('#random', () => { 17 | it('produces a integer n.', () => { 18 | const n = number.int.random; 19 | expect(isInteger(n)).eq(true); 20 | }); 21 | }); 22 | }); 23 | describe('Positive Integer', () => { 24 | describe('#random', () => { 25 | it('produces a integer n >= 0.', () => { 26 | const n = number.pint.random; 27 | expect(isInteger(n)).eq(true); 28 | expect(n).gte(0); 29 | }); 30 | }); 31 | }); 32 | describe('Negative Integer', () => { 33 | describe('#random', () => { 34 | it('produces a integer n < 0.', () => { 35 | const n = number.nint.random; 36 | expect(isInteger(n)).eq(true); 37 | expect(n).lt(0); 38 | }); 39 | }); 40 | }); 41 | describe('Nature Number', () => { 42 | describe('#random', () => { 43 | it('produces a integer n > 0', () => { 44 | const n = number.nat.random; 45 | expect(isNumber(n)).eq(true); 46 | expect(n).gt(0); 47 | }); 48 | }); 49 | }); 50 | describe('Number', () => { 51 | describe('#random', () => { 52 | it('produces a number n', () => { 53 | const n = number.num.random; 54 | expect(isNumber(n)).eq(true); 55 | }); 56 | }); 57 | }); 58 | describe('Positive Number', () => { 59 | describe('#random', () => { 60 | it('produces a number n >= 0', () => { 61 | const n = number.pnum.random; 62 | expect(isNumber(n)).eq(true); 63 | expect(n).gte(0); 64 | }); 65 | }); 66 | }); 67 | describe('Negative Number', () => { 68 | describe('#random', () => { 69 | it('produces a number n < 0', () => { 70 | const n = number.nnum.random; 71 | expect(isNumber(n)).eq(true); 72 | expect(n).lt(0); 73 | }); 74 | }); 75 | }); 76 | describe('Hex String', () => { 77 | describe('#choose()', () => { 78 | it('uppercase the hex string', () => { 79 | const n = number.hexString.choose({ upper: true }).random; 80 | const r = n.split('').reduce( 81 | (acc, c) => acc && !/[a-z]/.test(c), true); 82 | expect(r).eq(true); 83 | }); 84 | it('changes length', () => { 85 | const n = number.hexString.choose({ length: 2 }).random; 86 | expect(n.length).eq(2); 87 | }); 88 | }); 89 | describe('#random', () => { 90 | it('produces a hex string of length 6', () => { 91 | const n = number.hexString.random; 92 | expect(isString(n)).eq(true); 93 | expect(n.length).eq(6); 94 | }); 95 | }); 96 | }); 97 | }); -------------------------------------------------------------------------------- /src/types/primitive/number.ts: -------------------------------------------------------------------------------- 1 | import { defaults } from 'lodash'; 2 | import { 3 | Engine, 4 | integer, 5 | real, 6 | hex 7 | } from 'random-js'; 8 | import { Arbitrary } from '../../arbitrary'; 9 | import { shrinkNumber } from '../../shrink'; 10 | import { ulog2 } from '../../utils'; 11 | 12 | export interface NumberGenOpts { 13 | min: number, 14 | max: number 15 | } 16 | 17 | const defaultNumberGenOpts = { 18 | min: -Number.MAX_SAFE_INTEGER, 19 | max: Number.MAX_SAFE_INTEGER 20 | } 21 | 22 | /** 23 | * Take a pair of numbers and returns 24 | * their smaller size. 25 | */ 26 | function smallerRange(range: {min: number, max: number}): NumberGenOpts { 27 | return { 28 | min: ulog2(range.min), 29 | max: ulog2(range.max) 30 | }; 31 | } 32 | 33 | function intGen(opts: NumberGenOpts) { 34 | const {min, max} = defaults(opts, defaultNumberGenOpts); 35 | return (engine: Engine) => integer(min, max)(engine); 36 | } 37 | 38 | /** 39 | * Arbitrary Integer 40 | */ 41 | export const int = new Arbitrary({ 42 | gen: intGen, 43 | genOpts: defaultNumberGenOpts, 44 | shrinker: shrinkNumber, 45 | smaller: smallerRange 46 | }).set('name', 'Integer') 47 | 48 | /** 49 | * Arbitrary Positive Integer 50 | */ 51 | export const pint = int 52 | .choose({min: 0}) 53 | .set('definition', (n: number) => n >= 0) 54 | .set('name', 'Positive Integer'); 55 | 56 | /** 57 | * Arbitrary Negative Integer 58 | */ 59 | export const nint = int 60 | .choose({max: -1}) 61 | .set('definition', (n: number) => n <= -1) 62 | .set('name', 'Negative Integer'); 63 | 64 | 65 | /** 66 | * Arbitrary Nature Number 67 | */ 68 | export const nat = int 69 | .choose({min: 1}) 70 | .set('definition', (n: number) => n >= 1) 71 | .set('name', 'Nat'); 72 | 73 | function numberGen(opts: NumberGenOpts) { 74 | const {min, max} = defaults(opts, defaultNumberGenOpts); 75 | return (engine: Engine) => real(min, max, true)(engine); 76 | } 77 | 78 | /** 79 | * Arbitrary Number 80 | */ 81 | export const num = new Arbitrary({ 82 | gen: numberGen, 83 | genOpts: defaultNumberGenOpts, 84 | }).set('name', 'Number'); 85 | 86 | /** 87 | * Arbitrary Positive Number 88 | */ 89 | export const pnum = num 90 | .choose({min: 0}) 91 | .set('definition', (n:number) => n >= 0) 92 | .set('name', 'Positive Number'); 93 | 94 | /** 95 | * Arbitrary Negative Number 96 | */ 97 | export const nnum = num 98 | .choose({max: -0.000000001}) 99 | .set('definition', (n:number) => n <= -0.000000001) 100 | .set('name', 'Negative Number'); 101 | 102 | export interface HexStringGenOpts { 103 | upper: boolean, 104 | length: number 105 | } 106 | 107 | const defaultHexStringGenOpts = { 108 | upper: false, 109 | length: 6 110 | } 111 | 112 | function hexStringGen(opts: HexStringGenOpts) { 113 | const {upper, length} = defaults(opts, defaultHexStringGenOpts); 114 | return (engine: Engine) => hex(upper)(engine, length); 115 | } 116 | 117 | /** 118 | * Arbitrary Hex String 119 | */ 120 | export const hexString = new Arbitrary({ 121 | gen: hexStringGen, 122 | genOpts: defaultHexStringGenOpts 123 | }).set('name', 'Hex String'); -------------------------------------------------------------------------------- /src/types/primitive/string.ts: -------------------------------------------------------------------------------- 1 | import { int, NumberGenOpts } from './number'; 2 | import { promote } from '../../gen'; 3 | import { Arbitrary } from '../../arbitrary'; 4 | import { array, nearray} from '../../combinators/collections'; 5 | import { shrinkNoop } from '../../shrink'; 6 | 7 | export type Char = Arbitrary; 8 | export const rawChar: Char = int 9 | .transformWith( 10 | promote((n:number) => String.fromCharCode(n)), 11 | null, 12 | () => shrinkNoop 13 | ); 14 | 15 | export const ASCII_RANGE_MIN = 0x0020; 16 | export const ASCII_RANGE_MAX = 0x007F; 17 | export const UNICODE_RANGES_MIN = 0x0020; 18 | export const UNICODE_RANGES_MAX = 0xE007F; 19 | 20 | export function stringOf(char: Char) { 21 | return array(char) 22 | .transform(c => c.join('')) 23 | .set('name', 'StringOf'); 24 | } 25 | 26 | export function nestringOf(char: Char) { 27 | return nearray(char) 28 | .transform(c => c.join('')) 29 | .set('name', 'StringOf'); 30 | } 31 | 32 | /** 33 | * Unicode Character Arbitrary. 34 | */ 35 | export const char = rawChar 36 | .choose({min: UNICODE_RANGES_MIN, max: UNICODE_RANGES_MAX}) 37 | .set('name', 'Char'); 38 | 39 | /** 40 | * Unicode String Arbitrary. 41 | */ 42 | export const string = stringOf(char) 43 | .set('name', 'Unicode String'); 44 | 45 | /** 46 | * Non-Empty Unicode String Arbitrary. 47 | */ 48 | export const nestring = stringOf(char) 49 | .set('name', 'Non-Empty Unicode String'); 50 | 51 | /** 52 | * ASCII Character Arbitrary. 53 | */ 54 | export const asciichar = rawChar 55 | .choose({min: ASCII_RANGE_MIN, max: ASCII_RANGE_MAX}) 56 | .set('name', 'ASCII Char'); 57 | 58 | /** 59 | * ASCII String Arbitrary. 60 | */ 61 | export const asciistring = stringOf(asciichar) 62 | .set('name', 'ASCII String'); 63 | 64 | /** 65 | * Non-Empty ASCII String Arbitrary. 66 | */ 67 | export const neasciistring = stringOf(asciichar) 68 | .set('name', 'Non-Empty ASCII String'); -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { isInteger } from 'lodash'; 2 | 3 | export function div2(n: number) { 4 | const i = Math.floor(Math.abs(n / 2)); 5 | return n >= 0 ? i : -i; 6 | } 7 | 8 | export function ulog2(n: number): number { 9 | if (n === 0 ) return 0; 10 | const x = n < 0 ? Math.abs(n) : n; 11 | const xprime = Math.log2(x); 12 | const xprimeprime = isInteger(n) ? Math.floor(xprime) : xprime; 13 | return n < 0 ? -xprimeprime : xprimeprime; 14 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es2017", 5 | "module": "commonjs", 6 | "noImplicitReturns": true, 7 | "noFallthroughCasesInSwitch": true, 8 | "sourceMap": true, 9 | "strictNullChecks": true, 10 | "noImplicitAny": true, 11 | "declaration": true, 12 | "strict": true 13 | }, 14 | "lib": [ 15 | "ES2017", 16 | "dom" 17 | ], 18 | "include": [ 19 | "./src/**/*.ts" 20 | ], 21 | "exclude": [ 22 | "./src/**/*.test.ts" 23 | ] 24 | } 25 | --------------------------------------------------------------------------------