mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 17:12:43 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d7a0e10c6 | ||
|
|
4865f911d1 | ||
|
|
15ae5e0873 | ||
|
|
a246bdea84 | ||
|
|
8641bfc877 | ||
|
|
d34e66fbbc | ||
|
|
c6273a85d9 | ||
|
|
5558d29c2b | ||
|
|
69dfd1ae39 | ||
|
|
4638bb3684 | ||
|
|
6c687c6004 | ||
|
|
0bf1301733 | ||
|
|
827ba47892 | ||
|
|
d3b620a745 |
@@ -1,10 +1,5 @@
|
|||||||
image: registry.gitlab.com/openstapps/projectmanagement/node
|
image: registry.gitlab.com/openstapps/projectmanagement/node
|
||||||
|
|
||||||
cache:
|
|
||||||
key: ${CI_COMMIT_REF_SLUG}
|
|
||||||
paths:
|
|
||||||
- node_modules
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- npm install
|
- npm install
|
||||||
|
|
||||||
|
|||||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,3 +1,21 @@
|
|||||||
|
## [0.38.1](https://gitlab.com/openstapps/core/compare/v0.38.0...v0.38.1) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.38.0](https://gitlab.com/openstapps/core/compare/v0.37.0...v0.38.0) (2020-10-30)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.37.0](https://gitlab.com/openstapps/core/compare/v0.36.0...v0.37.0) (2020-09-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove keyword tag from steps ([c369c85](https://gitlab.com/openstapps/core/commit/c369c8520a2eed169555a35a50ce745c08e1f9da))
|
||||||
|
* remove redundant property declaration ([66075ef](https://gitlab.com/openstapps/core/commit/66075ef99b95198a9cd5c0a396603e089221bcd9))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [0.36.0](https://gitlab.com/openstapps/core/compare/v0.35.0...v0.36.0) (2020-07-16)
|
# [0.36.0](https://gitlab.com/openstapps/core/compare/v0.35.0...v0.36.0) (2020-07-16)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -35,16 +35,17 @@ node --require ts-node/register src/cli.ts routes PATH/TO/ROUTES.md
|
|||||||
Annotations are used to add additional informations to fields, which are used to autogenerate mappings from the core objects.
|
Annotations are used to add additional informations to fields, which are used to autogenerate mappings from the core objects.
|
||||||
External dependencies can not be covered by the annotations. Documentation about some of the annotations can be found in: [typedoc](https://typedoc.org/guides/doccomments/)
|
External dependencies can not be covered by the annotations. Documentation about some of the annotations can be found in: [typedoc](https://typedoc.org/guides/doccomments/)
|
||||||
|
|
||||||
| annotation | description | parameters |
|
| annotation | description | parameters |
|
||||||
|-------------------|-------------------------------------------|---------------|
|
|-------------------|-------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
|
||||||
| `@aggregatable` | used for generating of aggregations of the field if the core schema is used to put data into a database/key-value store | whether the property is being used on the top type or across all types: `global` |
|
| `@aggregatable` | used for generating of aggregations of the field if the core schema is used to put data into a database/key-value store | whether the property is being used on the top type or across all types: `global` |
|
||||||
| `@float` | number field is interpreted as float | |
|
| `@float` | number field is interpreted as float | |
|
||||||
| `@indexable` | marks the type as indexable if the core schema is used to put data into a database/key-value store| |
|
| `@indexable` | marks the type as indexable if the core schema is used to put data into a database/key-value store | |
|
||||||
| `@integer` | number field is interpreted as integer | |
|
| `@integer` | number field is interpreted as integer | |
|
||||||
| `@keyword` | string field is interpreted as keyword | |
|
| `@keyword` | string field is interpreted as keyword | |
|
||||||
| `@sortable` | field is sortable if the core schema is used to put data into a database/key-value store | sort method to be used: `ducet`, `price`, `distance` |
|
| `@sortable` | field is sortable if the core schema is used to put data into a database/key-value store | sort method to be used: `ducet`, `price`, `distance` |
|
||||||
| `@text` | string field is interpreted as text | |
|
| `@text` | string field is interpreted as text | |
|
||||||
| `@validatable` | marks the type as validatable if the core schema is used to put data into a database/key-value store | |
|
| `@validatable` | marks the type as validatable if the core schema is used to put data into a database/key-value store | |
|
||||||
| `@filterable` | non-object/nested field is filterable if the core schema is used to put data into a database/key-value store | |
|
| `@filterable` | non-object/nested field is filterable if the core schema is used to put data into a database/key-value store | |
|
||||||
|
| `@inheritTags` | inherit all tags from another field | `[SCThingType]::[field]` |
|
||||||
|
|
||||||
|
*Note: tags ignore casing, but for consistency they should use the variants proposed here.*
|
||||||
|
|||||||
2482
package-lock.json
generated
2482
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@openstapps/core",
|
"name": "@openstapps/core",
|
||||||
"version": "0.37.0",
|
"version": "0.39.0",
|
||||||
"description": "StAppsCore - Generalized model of data",
|
"description": "StAppsCore - Generalized model of data",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Model",
|
"Model",
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"preversion": "npm run prepublishOnly",
|
"preversion": "npm run prepublishOnly",
|
||||||
"push": "git push && git push origin \"v$npm_package_version\"",
|
"push": "git push && git push origin \"v$npm_package_version\"",
|
||||||
"schema": "node --max-old-space-size=8192 --stack-size=10240 ./node_modules/.bin/openstapps-core-tools schema src lib/schema",
|
"schema": "node --max-old-space-size=8192 --stack-size=10240 ./node_modules/.bin/openstapps-core-tools schema src lib/schema",
|
||||||
"test": "nyc mocha --require ts-node/register --require source-map-support/register --ui mocha-typescript test/*.spec.ts",
|
"test": "nyc mocha --require ts-node/register --recursive 'test/*.spec.ts'",
|
||||||
"tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'"
|
"tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'"
|
||||||
},
|
},
|
||||||
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
|
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
|
||||||
@@ -42,33 +42,34 @@
|
|||||||
"Roman Klopsch"
|
"Roman Klopsch"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@openstapps/core-tools": "0.16.0",
|
||||||
"@types/geojson": "1.0.6",
|
"@types/geojson": "1.0.6",
|
||||||
"@types/json-patch": "0.0.30",
|
"@types/json-patch": "0.0.30",
|
||||||
"@types/node": "10.17.14",
|
"@types/json-schema": "7.0.6",
|
||||||
|
"@types/node": "10.17.44",
|
||||||
"fast-clone": "1.5.13",
|
"fast-clone": "1.5.13",
|
||||||
"http-status-codes": "2.1.2",
|
"http-status-codes": "2.1.4",
|
||||||
"json-patch": "0.7.0",
|
"json-patch": "0.7.0",
|
||||||
"jsonschema": "1.2.5",
|
"json-schema": "0.2.5",
|
||||||
"ts-optchain": "0.1.8"
|
"ts-optchain": "0.1.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@openstapps/configuration": "0.24.0",
|
"@openstapps/configuration": "0.25.0",
|
||||||
"@openstapps/core-tools": "0.14.0",
|
|
||||||
"@openstapps/logger": "0.5.0",
|
"@openstapps/logger": "0.5.0",
|
||||||
"@types/chai": "4.2.12",
|
"@testdeck/mocha": "0.1.2",
|
||||||
|
"@types/chai": "4.2.14",
|
||||||
"@types/rimraf": "3.0.0",
|
"@types/rimraf": "3.0.0",
|
||||||
"chai": "4.2.0",
|
"chai": "4.2.0",
|
||||||
"conditional-type-checks": "1.0.5",
|
"conditional-type-checks": "1.0.5",
|
||||||
"conventional-changelog-cli": "2.1.0",
|
"conventional-changelog-cli": "2.1.0",
|
||||||
"mocha": "8.1.1",
|
"mocha": "8.2.0",
|
||||||
"mocha-typescript": "1.1.17",
|
|
||||||
"nyc": "15.1.0",
|
"nyc": "15.1.0",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"source-map-support": "0.5.19",
|
"source-map-support": "0.5.19",
|
||||||
"ts-node": "9.0.0",
|
"ts-node": "9.0.0",
|
||||||
"tslint": "6.1.3",
|
"tslint": "6.1.3",
|
||||||
"typedoc": "0.14.2",
|
"typedoc": "0.18.0",
|
||||||
"typescript": "3.5.3"
|
"typescript": "3.8.3"
|
||||||
},
|
},
|
||||||
"nyc": {
|
"nyc": {
|
||||||
"all": true,
|
"all": true,
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
import {ValidationError} from '@openstapps/core-tools/lib/common';
|
||||||
import {BAD_REQUEST} from 'http-status-codes';
|
import {BAD_REQUEST} from 'http-status-codes';
|
||||||
import {ValidationError} from 'jsonschema';
|
|
||||||
import {SCError} from '../error';
|
import {SCError} from '../error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {OK} from 'http-status-codes';
|
import {OK} from 'http-status-codes';
|
||||||
import {Schema} from 'jsonschema';
|
import {JSONSchema7} from 'json-schema';
|
||||||
import {SCInternalServerErrorResponse} from '../errors/internal-server-error';
|
import {SCInternalServerErrorResponse} from '../errors/internal-server-error';
|
||||||
import {SCMethodNotAllowedErrorResponse} from '../errors/method-not-allowed';
|
import {SCMethodNotAllowedErrorResponse} from '../errors/method-not-allowed';
|
||||||
import {SCNotFoundErrorResponse} from '../errors/not-found';
|
import {SCNotFoundErrorResponse} from '../errors/not-found';
|
||||||
@@ -78,12 +78,12 @@ export interface SCPluginMetaData {
|
|||||||
/**
|
/**
|
||||||
* How the requests of the plugin looks like, a JSON schema for validation
|
* How the requests of the plugin looks like, a JSON schema for validation
|
||||||
*/
|
*/
|
||||||
requestSchema: Schema;
|
requestSchema: JSONSchema7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How the responses of the plugin looks like, a JSON schema for validation
|
* How the responses of the plugin looks like, a JSON schema for validation
|
||||||
*/
|
*/
|
||||||
responseSchema: Schema;
|
responseSchema: JSONSchema7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The desired route, for example /feedback.
|
* The desired route, for example /feedback.
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ export class SCThingTranslator {
|
|||||||
* // or
|
* // or
|
||||||
* const dishTranslatedAccess = translator.translate(dish);
|
* const dishTranslatedAccess = translator.translate(dish);
|
||||||
* dishTranslatedAccess.offers[0].inPlace.categories[1]();
|
* dishTranslatedAccess.offers[0].inPlace.categories[1]();
|
||||||
* // undoing the TSTSOCType<T>
|
* // undoing the TSOCType<T>
|
||||||
* const dishAsBefore: SCDish = dishTranslatedAccess()!;
|
* const dishAsBefore: SCDish = dishTranslatedAccess()!;
|
||||||
* @param data Top level object that gets passed through the recursion
|
* @param data Top level object that gets passed through the recursion
|
||||||
* @returns an TSOCType<T> object allowing for access to translations or a translated value(s)
|
* @returns an TSOCType<T> object allowing for access to translations or a translated value(s)
|
||||||
@@ -224,29 +224,27 @@ export class SCThingTranslator {
|
|||||||
*/
|
*/
|
||||||
public translatedPropertyNames<T extends SCThing>(type: SCThingType,
|
public translatedPropertyNames<T extends SCThing>(type: SCThingType,
|
||||||
language?: keyof SCTranslations<T>): T | undefined {
|
language?: keyof SCTranslations<T>): T | undefined {
|
||||||
const targetLanguage = (typeof language !== 'undefined') ? language : this.language;
|
return this.getAllMetaFieldTranslations(type, language ?? this.language) as T;
|
||||||
|
|
||||||
return this.getAllMetaFieldTranslations(type, targetLanguage) as T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a SCThingType this function will translate it
|
* Given a SCThingType and a corresponding property name it returns the known property value translation
|
||||||
*
|
* Access pattern to the meta object containing the translation can be thought of as type.field[key] with key being optional
|
||||||
* @param type The type that will be translated
|
* @example
|
||||||
* @param language The language the type will be translated to
|
* const translatedMetaDish = translator.translatedPropertyNames(SCThingType.Dish, 'categories', 'main dish');
|
||||||
* @returns Known translation of type parameter
|
* @param type The type for whose property values a translation is required
|
||||||
|
* @param field The property for which a translation is required
|
||||||
|
* @param key If specified tries to access the field with this key
|
||||||
|
* @param language The language all property names will be translated to
|
||||||
|
* @returns Known translation for the property
|
||||||
*/
|
*/
|
||||||
public translatedThingType<T extends unknown>(type: SCThingType,
|
public translatedPropertyValue<T extends unknown>(type: SCThingType,
|
||||||
language?: keyof SCTranslations<T>): string {
|
field: string,
|
||||||
const targetLanguage = (typeof language !== 'undefined') ? language : this.language;
|
key?: string,
|
||||||
const metaClass = this.getMetaClassInstance(type);
|
language?: keyof SCTranslations<T>): string | undefined {
|
||||||
|
const fieldTranslation = this.getMetaClassInstance(type).fieldValueTranslations[language ?? this.language]?.[field];
|
||||||
|
|
||||||
if (typeof metaClass.fieldValueTranslations[targetLanguage] !== 'undefined' &&
|
return fieldTranslation?.[key ?? ''] ?? key ?? fieldTranslation;
|
||||||
typeof metaClass.fieldValueTranslations[targetLanguage].type !== 'undefined') {
|
|
||||||
return metaClass.fieldValueTranslations[targetLanguage].type as string ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import {slow, suite, test, timeout} from 'mocha-typescript';
|
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||||
import {SCBulkResponse} from '../src/protocol/routes/bulk-request';
|
import {SCBulkResponse} from '../src/protocol/routes/bulk-request';
|
||||||
import {SCMultiSearchResponse} from '../src/protocol/routes/search-multi';
|
import {SCMultiSearchResponse} from '../src/protocol/routes/search-multi';
|
||||||
import {SCSearchResponse} from '../src/protocol/routes/search';
|
import {SCSearchResponse} from '../src/protocol/routes/search';
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"address": "http://foo.com:1234",
|
"address": "http://foo.com:1234",
|
||||||
"name": "Foo Plugin",
|
"name": "Foo Plugin",
|
||||||
"requestSchema": {
|
"requestSchema": {
|
||||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"SCFooPluginRequest": {
|
"SCFooPluginRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "User query",
|
"description": "User query",
|
||||||
"id": "https://core.stapps.tu-berlin.de/v0.18.0/lib/schema/SCFooPluginRequest.json"
|
"$id": "https://core.stapps.tu-berlin.de/v0.18.0/lib/schema/SCFooPluginRequest.json"
|
||||||
},
|
},
|
||||||
"responseSchema": {
|
"responseSchema": {
|
||||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"SCFooPluginResponse": {
|
"SCFooPluginResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "A response to a query",
|
"description": "A response to a query",
|
||||||
"id": "https://core.stapps.tu-berlin.de/v0.18.0/lib/schema/SCFooPluginResponse.json"
|
"$id": "https://core.stapps.tu-berlin.de/v0.18.0/lib/schema/SCFooPluginResponse.json"
|
||||||
},
|
},
|
||||||
"route": "/foo"
|
"route": "/foo"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import {slow, suite, test, timeout} from 'mocha-typescript';
|
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||||
import {SCBulkRoute} from '../src/protocol/routes/bulk-request';
|
import {SCBulkRoute} from '../src/protocol/routes/bulk-request';
|
||||||
import {SCBulkAddRoute} from '../src/protocol/routes/bulk-add';
|
import {SCBulkAddRoute} from '../src/protocol/routes/bulk-add';
|
||||||
import {SCThingUpdateRoute} from '../src/protocol/routes/thing-update';
|
import {SCThingUpdateRoute} from '../src/protocol/routes/thing-update';
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {Logger} from '@openstapps/logger';
|
|||||||
import {fail} from 'assert';
|
import {fail} from 'assert';
|
||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import {mkdirSync} from 'fs';
|
import {mkdirSync} from 'fs';
|
||||||
import {slow, suite, test, timeout} from 'mocha-typescript';
|
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||||
import {join, resolve} from 'path';
|
import {join, resolve} from 'path';
|
||||||
import {DeclarationReflection, ProjectReflection} from 'typedoc';
|
import {DeclarationReflection, ProjectReflection} from 'typedoc';
|
||||||
import {ArrayType, IntrinsicType, ReferenceType, StringLiteralType, Type, UnionType} from 'typedoc/dist/lib/models';
|
import {ArrayType, IntrinsicType, ReferenceType, StringLiteralType, Type, UnionType} from 'typedoc/dist/lib/models';
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import clone = require('fast-clone');
|
import clone = require('fast-clone');
|
||||||
import {slow, suite, test, timeout} from 'mocha-typescript';
|
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||||
import {SCThingOriginType, SCThingType} from '../src/things/abstract/thing';
|
import {SCThingOriginType, SCThingType} from '../src/things/abstract/thing';
|
||||||
import {SCBuildingWithoutReferences} from '../src/things/building';
|
import {SCBuildingWithoutReferences} from '../src/things/building';
|
||||||
import {SCDish, SCDishMeta} from '../src/things/dish';
|
import {SCDish, SCDishMeta} from '../src/things/dish';
|
||||||
@@ -269,13 +269,23 @@ export class MetaTranslationSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test
|
@test
|
||||||
public retrieveTranslatedThingType() {
|
public retrieveTranslatedPropertyValueType() {
|
||||||
const dishTypeDE = translator.translatedThingType(dish.type);
|
const dishTypeDE = translator.translatedPropertyValue(dish.type, 'type');
|
||||||
const dishTypeEN = translator.translatedThingType(dish.type, 'en');
|
const dishTypeEN = translator.translatedPropertyValue(dish.type, 'type', undefined, 'en');
|
||||||
const dishTypeBASE = translatorWithFallback.translatedThingType(dish.type);
|
const dishTypeBASE = translatorWithFallback.translatedPropertyValue(dish.type, 'type');
|
||||||
expect(dishTypeDE).to.deep.equal(SCDishMeta.getInstance().fieldValueTranslations.de.type);
|
expect(dishTypeDE).to.deep.equal(SCDishMeta.getInstance().fieldValueTranslations.de.type);
|
||||||
expect(dishTypeEN).to.deep.equal(SCDishMeta.getInstance().fieldValueTranslations.en.type);
|
expect(dishTypeEN).to.deep.equal(SCDishMeta.getInstance().fieldValueTranslations.en.type);
|
||||||
expect(dishTypeBASE).to.deep.equal(SCDishMeta.getInstance().fieldValueTranslations.en.type);
|
expect(dishTypeBASE).to.be.undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
public retrieveTranslatedPropertyValueNested() {
|
||||||
|
const dishTypeDE = translator.translatedPropertyValue<SCDish>(dish.type, 'categories', 'main dish');
|
||||||
|
const dishTypeEN = translator.translatedPropertyValue<SCDish>(dish.type, 'categories', 'main dish', 'en');
|
||||||
|
const dishTypeBASE = translatorWithFallback.translatedPropertyValue(dish.type, 'categories', 'main dish');
|
||||||
|
expect(dishTypeDE).to.deep.equal(SCDishMeta.getInstance<SCDishMeta>().fieldValueTranslations.de.categories['main dish']);
|
||||||
|
expect(dishTypeEN).to.deep.equal(dish.categories[0]);
|
||||||
|
expect(dishTypeBASE).to.deep.equal(dish.categories[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@test
|
@test
|
||||||
|
|||||||
Reference in New Issue
Block a user