diff --git a/github-page/_docs/decorators/arrayProp.md b/github-page/_docs/decorators/arrayProp.md index a4422035b..53a79cb9a 100644 --- a/github-page/_docs/decorators/arrayProp.md +++ b/github-page/_docs/decorators/arrayProp.md @@ -61,6 +61,68 @@ class Another extends Typegoose { } ``` +### innerOptions + +`innerOptions` is used to overwrite here the options in this object go +-> Use this only when absolutly needed and please open a new issue about it - or for plugins + +Example: + +```ts +class Something { + @arrayProp({ required: true }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String }], + required: true +} + +// when using the overwrite +class Something { + @arrayProp({ innerOptions: { required: true } }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String, required: true }] +} +``` + +### outerOptions + +`outerOptions` is used to overwrite here the options in this object go +-> Use this only when absolutly needed and please open a new issue about it - or for plugins + +Example: + +```ts +class Something { + @arrayProp({ maxlength: 1 }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String, maxlength: 1 }] +} + +// when using the overwrite +class Something { + @arrayProp({ outerOptions: { maxlength: 1 } }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String }], + maxlength: 1 +} +``` + ## Options from @prop that do **NOT** work on @arrayProp - `ref` does not work, instead use `itemsRef` (please let us know if you are interested in combining them into one) diff --git a/github-page/changelog.md b/github-page/changelog.md index 08e030036..47d653606 100644 --- a/github-page/changelog.md +++ b/github-page/changelog.md @@ -18,6 +18,7 @@ redirect_from: - `@prop({ validate })` now accepts `{ validator, message }` as an array - Add function "deleteModel" & "deleteModelWithClass" - allow Prop Option "type" to overwrite the inferred type [look here for an example](https://typegoose.github.io/typegoose/docs/decorators/prop/#type) +- integrate "Array Validators & Transform" tests {% include gitissue repo="typegoose" num=29 %} - [IC] Refactor how "isPrimitive" works, some types like `Buffer` & `Decimal` now work - [IC] Added more debug logs to `prop.ts` - [IC] Move Decorator Cache to the class itself diff --git a/package-lock.json b/package-lock.json index 5ad829862..49f6f6c13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -181,9 +181,9 @@ } }, "@types/mongoose": { - "version": "5.5.20", - "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.5.20.tgz", - "integrity": "sha512-vaLVDjfuNp2LMfqHGMss4hN/K9puZfql/Rh6yXFvJvex3jKP646CXtvSKT8FM9uOUb2P4me266fmpPovBhEJXQ==", + "version": "5.5.22", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.5.22.tgz", + "integrity": "sha512-1AXWXzpt7MZTxsm0cg2Nd6vkZHtKF5poHESJAIp31AKDxN6YXTThg1LRUmKC9tIsdKHD+y8v2KeoO/sZeR/+OQ==", "dev": true, "requires": { "@types/mongodb": "*", @@ -196,6 +196,12 @@ "integrity": "sha512-kaYyLYf6ICn6/isAyD4K1MyWWd5Q3JgH6bnMN089LUx88+s4W8GvK9Q6JMBVu5vsFFp7pMdSxdKmlBXwH/VFRg==", "dev": true }, + "@types/semver": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.2.tgz", + "integrity": "sha512-G1Ggy7/9Nsa1Jt2yiBR2riEuyK2DFNnqow6R7cromXPMNynackRY1vqFTLz/gwnef1LHokbXThcPhqMRjUbkpQ==", + "dev": true + }, "agent-base": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", @@ -598,9 +604,9 @@ "dev": true }, "coveralls": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.6.tgz", - "integrity": "sha512-Pgh4v3gCI4T/9VijVrm8Ym5v0OgjvGLKj3zTUwkvsCiwqae/p6VLzpsFNjQS2i6ewV7ef+DjFJ5TSKxYt/mCrA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.7.tgz", + "integrity": "sha512-mUuH2MFOYB2oBaA4D4Ykqi9LaEYpMMlsiOMJOrv358yAjP6enPIk55fod2fNJ8AvwoYXStWQls37rA+s5e7boA==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -643,6 +649,14 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "dashdash": { @@ -891,9 +905,9 @@ } }, "es-abstract": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz", - "integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", "dev": true, "requires": { "es-to-primitive": "^1.2.0", @@ -904,8 +918,8 @@ "is-regex": "^1.0.4", "object-inspect": "^1.6.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.0.0", - "string.prototype.trimright": "^2.0.0" + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { @@ -1333,9 +1347,9 @@ "dev": true }, "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", "dev": true }, "is-callable": { @@ -1723,6 +1737,12 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -1753,6 +1773,13 @@ "integrity": "sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==", "dev": true }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "dev": true, + "optional": true + }, "merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -1818,9 +1845,9 @@ } }, "mocha": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.1.tgz", - "integrity": "sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", + "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -1884,6 +1911,7 @@ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", "integrity": "sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==", "dev": true, + "optional": true, "requires": { "bson": "^1.1.1", "require_optional": "^1.0.1", @@ -2014,14 +2042,14 @@ } }, "mongoose": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.4.tgz", - "integrity": "sha512-IgqQS5HIaZ8tG2cib6QllfIw2Wc/A0QVOsdKLsSqRolqJFWOjI0se3vsKXLNkbEcuJ1xziW3e/jPhBs65678Hg==", + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.6.tgz", + "integrity": "sha512-2r87HmQMDCeZocoFmYGnJSpCW9ut95iQyPUcseG2B6EiAJjJBmR3pA01QyDF2+zQWpA8Ui4wH7xOq05U1nF6wg==", "dev": true, "requires": { "bson": "~1.1.1", "kareem": "2.3.1", - "mongodb": "3.3.2", + "mongodb": "3.3.3", "mongoose-legacy-pluralize": "1.0.2", "mpath": "0.6.0", "mquery": "3.2.2", @@ -2030,6 +2058,20 @@ "safe-buffer": "5.1.2", "sift": "7.0.1", "sliced": "1.0.1" + }, + "dependencies": { + "mongodb": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.3.tgz", + "integrity": "sha512-MdRnoOjstmnrKJsK8PY0PjP6fyF/SBS4R8coxmhsfEU7tQ46/J6j+aSHF2n4c2/H8B+Hc/Klbfp8vggZfI0mmA==", + "dev": true, + "requires": { + "bson": "^1.1.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + } } }, "mongoose-findorcreate": { @@ -2132,6 +2174,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "npm-run-path": { @@ -2210,6 +2260,14 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "execa": { @@ -2926,6 +2984,14 @@ "requires": { "resolve-from": "^2.0.0", "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "resolve": { @@ -2980,6 +3046,16 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "dev": true, + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "seek-bzip": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", @@ -2990,10 +3066,9 @@ } }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "set-blocking": { "version": "2.0.0", @@ -3069,6 +3144,16 @@ } } }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "dev": true, + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, "spawn-wrap": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", @@ -3431,6 +3516,12 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, diff --git a/package.json b/package.json index 6b6e2e0c9..d6ea6a11d 100644 --- a/package.json +++ b/package.json @@ -34,21 +34,22 @@ ], "license": "MIT", "peerDependencies": { - "mongoose": "^5.7.4" + "mongoose": "^5.7.6" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^0.1.3", "@types/chai": "^4.2.3", "@types/chai-as-promised": "^7.1.2", "@types/mocha": "^5.2.7", - "@types/mongoose": "^5.5.20", + "@types/mongoose": "^5.5.22", "@types/node": "^8.10.53", + "@types/semver": "^6.0.2", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "coveralls": "^3.0.6", - "mocha": "^6.2.1", + "coveralls": "^3.0.7", + "mocha": "^6.2.2", "mongodb-memory-server-global": "^5.2.8", - "mongoose": "^5.7.4", + "mongoose": "^5.7.6", "mongoose-findorcreate": "^3.0.0", "nyc": "^14.1.1", "prettier": "^1.18.2", @@ -62,7 +63,8 @@ }, "dependencies": { "loglevel": "^1.6.4", - "reflect-metadata": "^0.1.13" + "reflect-metadata": "^0.1.13", + "semver": "^6.3.0" }, "publishConfig": { "access": "public" diff --git a/src/internal/utils.ts b/src/internal/utils.ts index cbb495b0a..47ff4b3dc 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -1,6 +1,7 @@ import * as mongoose from 'mongoose'; import { isNullOrUndefined } from 'util'; +import { logger } from '../logSettings'; import { AnyParamConstructor, IModelOptions, @@ -294,3 +295,57 @@ export function createUniqueID(cl: any) { return false; } + +/** + * Map Options to "inner" & "outer" + * -> inner: means inner of "type: [{here})" + * -> outer: means outer of "type: [{}], here" + * @param rawOptions The raw options + * @param Type The Type of the array + */ +export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor): mongoose.SchemaTypeOpts { + if (getName(Type) in mongoose.Schema.Types) { + logger.info('Converting %s to mongoose Type', getName(Type)); + Type = mongoose.Schema.Types[getName(Type)]; + } else if (isNullOrUndefined(Type.prototype.OptionsConstructor)) { + throw new TypeError('Type does not have an valid "OptionsConstructor"!'); + } + + const options = Object.assign({}, rawOptions); // for sanity + + delete options.items; + + const returnObject = { + type: [{ + type: Type + }] + }; + + // "mongoose as any" is because the types package does not yet have an entry for "SchemaTypeOptions" + if (Type.prototype.OptionsConstructor.prototype instanceof (mongoose as any).SchemaTypeOptions) { + for (const [key, value] of Object.entries(options)) { + if (Object.getOwnPropertyNames(Type.prototype.OptionsConstructor.prototype).includes(key)) { + returnObject.type[0][key] = value; + } else { + returnObject[key] = value; + } + } + } else { + logger.info('The Type "%s" does not have an OptionsConstructor', getName(Type)); + } + + if (typeof options.innerOptions === 'object') { + for (const [key, value] of Object.entries(options.innerOptions)) { + returnObject.type[0][key] = value; + } + } + if (typeof options.outerOptions === 'object') { + for (const [key, value] of Object.entries(options.outerOptions)) { + returnObject[key] = value; + } + } + + logger.debug('Final mapped Options for Type "%s"', getName(Type), returnObject); + + return returnObject; +} diff --git a/src/prop.ts b/src/prop.ts index 0d31c4208..447b1600b 100644 --- a/src/prop.ts +++ b/src/prop.ts @@ -240,8 +240,7 @@ export function _buildPropMetadata(input: DecoratedPropertyMetadata) { case WhatIsIt.ARRAY: schemas.get(name)[key] = { ...schemas.get(name)[key][0], - ...options, - type: [Type] + ...utils.mapArrayOptions(rawOptions, Type) }; return; diff --git a/src/typegoose.ts b/src/typegoose.ts index 723835f96..7fe2ac0c8 100644 --- a/src/typegoose.ts +++ b/src/typegoose.ts @@ -1,8 +1,13 @@ /* imports */ import * as mongoose from 'mongoose'; import 'reflect-metadata'; +import * as semver from 'semver'; import { deprecate, isNullOrUndefined } from 'util'; +if (semver.lt(mongoose.version, '5.7.6')) { + throw new Error('Please use mongoose 5.7.6 or higher'); +} + import * as defaultClasses from './defaultClasses'; import { DecoratorKeys } from './internal/constants'; import { constructors, models } from './internal/data'; diff --git a/src/types.ts b/src/types.ts index f01418bea..59ebc3d7f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -243,6 +243,24 @@ export interface ArrayPropOptions extends BasePropOptions { itemsRefPath?: any; /** Same as {@link PropOptions.refType}, only that it is for an array */ itemsRefType?: RefSchemaType; + /** + * Use this to define inner-options + * Use this if the auto-mapping is not correct or for plugin options + * + * Please open a new issue if some option is mismatched or not existing / mapped + */ + innerOptions?: { + [key: string]: any; + }; + /** + * Use this to define outer-options + * Use this if the auto-mapping is not correct or for plugin options + * + * Please open a new issue if some option is mismatched or not existing / mapped + */ + outerOptions?: { + [key: string]: any; + }; } export interface MapPropOptions extends BasePropOptions { diff --git a/test/index.test.ts b/test/index.test.ts index 154572e16..6d3f0a104 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,6 +1,7 @@ import { use } from 'chai'; import * as cap from 'chai-as-promised'; +import { suite as ArrayValidatorTests } from './tests/arrayValidator.test'; import { suite as BigUserTest } from './tests/biguser.test'; import { suite as customNameTests } from './tests/customName.test'; import { suite as IndexTests } from './tests/dbIndex.test'; @@ -36,6 +37,8 @@ describe('Typegoose', () => { describe('String Validators', StringValidatorTests.bind(this)); + describe('Array Validators', ArrayValidatorTests.bind(this)); + describe('getClassForDocument()', GCFDTest.bind(this)); describe('Should Error', ErrorTests.bind(this)); diff --git a/test/models/arrayValidators.ts b/test/models/arrayValidators.ts new file mode 100644 index 000000000..12f94733f --- /dev/null +++ b/test/models/arrayValidators.ts @@ -0,0 +1,28 @@ +import { arrayProp, getModelForClass } from '../../src/typegoose'; + +// Please try to keep this file in sync with ./stringValidators.ts + +export class ArrayValidators { + @arrayProp({ items: String, maxlength: 3 }) + public maxLength: string[]; + + @arrayProp({ items: String, minlength: 10 }) + public minLength: string[]; + + @arrayProp({ items: String, trim: true }) + public trimmed: string[]; + + @arrayProp({ items: String, uppercase: true }) + public uppercased: string[]; + + @arrayProp({ items: String, lowercase: true }) + public lowercased: string[]; + + @arrayProp({ items: String, enum: ['one', 'two', 'three'] }) + public enumed: string[]; + + @arrayProp({ items: String, default: ['hello'], lowercase: true }) + public defaulted: string[]; +} + +export const model = getModelForClass(ArrayValidators); diff --git a/test/models/stringValidators.ts b/test/models/stringValidators.ts index 1112591c6..1e1935f34 100644 --- a/test/models/stringValidators.ts +++ b/test/models/stringValidators.ts @@ -1,5 +1,7 @@ import { getModelForClass, prop } from '../../src/typegoose'; +// Please try to keep this file in sync with ./arrayValidators.ts + export class StringValidators { @prop({ maxlength: 3 }) public maxLength: string; diff --git a/test/tests/arrayValidator.test.ts b/test/tests/arrayValidator.test.ts new file mode 100644 index 000000000..d9ade2439 --- /dev/null +++ b/test/tests/arrayValidator.test.ts @@ -0,0 +1,56 @@ +import { expect } from 'chai'; +import * as mongoose from 'mongoose'; + +import { model as ArrayValidators } from '../models/arrayValidators'; + +// Please try to keep this file in sync with ./stringValidator.test.ts + +/** + * Function to pass into describe + * ->Important: you need to always bind this + */ +export function suite() { + it('should respect maxlength', (done) => { + expect(ArrayValidators.create({ + maxLength: ['this is too long'] + })).to.eventually.rejectedWith(mongoose.Error.ValidationError).and.notify(done); + }); + + it('should respect minlength', (done) => { + expect(ArrayValidators.create({ + minLength: ['too short'] + })).to.eventually.rejectedWith(mongoose.Error.ValidationError).and.notify(done); + }); + + it('should trim', async () => { + const trimmed = await ArrayValidators.create({ + trimmed: ['trim my end '] + }); + expect(trimmed.trimmed[0]).equals('trim my end'); + }); + + it('should uppercase', async () => { + const uppercased = await ArrayValidators.create({ + uppercased: ['make me uppercase'] + }); + expect(uppercased.uppercased[0]).equals('MAKE ME UPPERCASE'); + }); + + it('should lowercase', async () => { + const lowercased = await ArrayValidators.create({ + lowercased: ['MAKE ME LOWERCASE'] + }); + expect(lowercased.lowercased[0]).equals('make me lowercase'); + }); + + it('should respect enum', (done) => { + expect(ArrayValidators.create({ + enumed: ['not in the enum'] + })).to.eventually.rejectedWith(mongoose.Error).and.notify(done); + }); + + it('should lowercase & have a default', async () => { + const defaulted = await ArrayValidators.create({}); + expect(defaulted.defaulted[0]).equals('hello'); + }); +} diff --git a/test/tests/stringValidator.test.ts b/test/tests/stringValidator.test.ts index 4e8dc4af5..be6316595 100644 --- a/test/tests/stringValidator.test.ts +++ b/test/tests/stringValidator.test.ts @@ -3,16 +3,11 @@ import * as mongoose from 'mongoose'; import { model as StringValidators } from '../models/stringValidators'; +// Please try to keep this file in sync with ./arrayValidator.test.ts + /** * Function to pass into describe * ->Important: you need to always bind this - * @example - * ``` - * import { suite as StringValidatorTests } from './stringValidator.test' - * ... - * describe('String Validators', StringValidatorTests.bind(this)); - * ... - * ``` */ export function suite() { it('should respect maxlength', (done) => {