mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-10 11:42:59 +00:00
feat: tests
This commit is contained in:
@@ -13,41 +13,31 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {lightweightProjectFromPath} from '@openstapps/core-tools/lib/easy-ast/easy-ast';
|
||||
import {LightweightProject} from '@openstapps/core-tools/lib/easy-ast/types/lightweight-project';
|
||||
import {lightweightProjectFromPath, LightweightProject} from '@openstapps/easy-ast';
|
||||
import {expect} from 'chai';
|
||||
import {reduce} from 'lodash';
|
||||
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
process.on('unhandledRejection', error => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
describe('Mapping Compatibility', () => {
|
||||
let project: LightweightProject;
|
||||
|
||||
before(function () {
|
||||
this.timeout(15000);
|
||||
this.slow(10000);
|
||||
this.timeout(15_000);
|
||||
this.slow(10_000);
|
||||
|
||||
project = lightweightProjectFromPath('src');
|
||||
});
|
||||
|
||||
it('non-exported definitions should not have duplicate names across files', () => {
|
||||
reduce(
|
||||
project,
|
||||
(result, file) =>
|
||||
reduce(
|
||||
file,
|
||||
(result2, _, key) => {
|
||||
expect(result2[key]).to.be.undefined;
|
||||
return {
|
||||
[key]: true,
|
||||
...result2,
|
||||
};
|
||||
},
|
||||
result,
|
||||
),
|
||||
{} as Record<string, boolean>,
|
||||
);
|
||||
const names = new Set<string>();
|
||||
|
||||
for (const file in project) {
|
||||
for (const definition in project[file]) {
|
||||
expect(names).not.to.include(definition);
|
||||
names.add(definition);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
33
packages/core/test/dummy/building.ts
Normal file
33
packages/core/test/dummy/building.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import {SCBuildingWithoutReferences, SCThingType} from '../../src/index.js';
|
||||
|
||||
export const building: SCBuildingWithoutReferences = {
|
||||
address: {
|
||||
addressCountry: 'base-address.addressCountry',
|
||||
addressLocality: 'base-address.addressLocality',
|
||||
postalCode: 'base-address.postalCode',
|
||||
streetAddress: 'base-address.streetAddress',
|
||||
},
|
||||
categories: ['office', 'education'],
|
||||
floors: ['base-floor0', 'base-floor1'],
|
||||
geo: {
|
||||
point: {
|
||||
coordinates: [12, 13],
|
||||
type: 'Point',
|
||||
},
|
||||
},
|
||||
name: 'base-space-name',
|
||||
translations: {
|
||||
de: {
|
||||
address: {
|
||||
addressCountry: 'de-address.addressCountry',
|
||||
addressLocality: 'de-address.addressLocality',
|
||||
postalCode: 'de-address.postalCode',
|
||||
streetAddress: 'de-address.streetAddress',
|
||||
},
|
||||
floors: ['de-floor0', 'de-floor1'],
|
||||
name: 'de-space-name',
|
||||
},
|
||||
},
|
||||
type: SCThingType.Building,
|
||||
uid: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
};
|
||||
9
packages/core/test/dummy/bulk-response.ts
Normal file
9
packages/core/test/dummy/bulk-response.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import {SCBulkResponse, SCThingType} from '../../src/index.js';
|
||||
|
||||
export const bulkResponse: SCBulkResponse = {
|
||||
expiration: '2009-06-30T18:30:00+02:00 ',
|
||||
source: 'bar',
|
||||
state: 'done',
|
||||
type: SCThingType.Dish,
|
||||
uid: 'foo',
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import {SCSearchResponse} from '../../src/index.js';
|
||||
import {dishWithTranslation} from './dish-with-translation.js';
|
||||
|
||||
export const dishWithTranslationSearchResponse: SCSearchResponse = {
|
||||
data: [dishWithTranslation],
|
||||
facets: [
|
||||
{
|
||||
buckets: [
|
||||
{
|
||||
count: 1,
|
||||
key: 'key',
|
||||
},
|
||||
],
|
||||
field: 'field',
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
count: 1,
|
||||
offset: 0,
|
||||
total: 1,
|
||||
},
|
||||
stats: {
|
||||
time: 1,
|
||||
},
|
||||
};
|
||||
17
packages/core/test/dummy/dish-with-translation.ts
Normal file
17
packages/core/test/dummy/dish-with-translation.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import {SCDish, SCThingOriginType, SCThingType} from '../../src/index.js';
|
||||
|
||||
export const dishWithTranslation: SCDish = {
|
||||
categories: ['appetizer'],
|
||||
name: 'foo',
|
||||
origin: {
|
||||
created: '',
|
||||
type: SCThingOriginType.User,
|
||||
},
|
||||
translations: {
|
||||
de: {
|
||||
name: 'Foo',
|
||||
},
|
||||
},
|
||||
type: SCThingType.Dish,
|
||||
uid: 'bar',
|
||||
};
|
||||
35
packages/core/test/dummy/dish.ts
Normal file
35
packages/core/test/dummy/dish.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import {SCDish, SCThingOriginType, SCThingType} from '../../src/index.js';
|
||||
import {building} from './building.js';
|
||||
|
||||
export const dish: SCDish = {
|
||||
categories: ['main dish', 'dessert'],
|
||||
characteristics: [{name: 'base-characteristic0'}, {name: 'base-characteristic1'}],
|
||||
name: 'base-dish-name',
|
||||
offers: [
|
||||
{
|
||||
availability: 'in stock',
|
||||
inPlace: building,
|
||||
prices: {
|
||||
default: 23.42,
|
||||
},
|
||||
provider: {
|
||||
name: 'base-provider',
|
||||
type: SCThingType.Organization,
|
||||
uid: '540862f3-ea30-5b8f-8678-56b4dc217141',
|
||||
},
|
||||
},
|
||||
],
|
||||
origin: {
|
||||
indexed: '1970-01-01T00:00:00.000Z',
|
||||
name: 'dish-connector',
|
||||
type: SCThingOriginType.Remote,
|
||||
},
|
||||
translations: {
|
||||
de: {
|
||||
characteristics: [{name: 'de-characteristic0'}, {name: 'de-characteristic1'}],
|
||||
name: 'de-dish-name',
|
||||
},
|
||||
},
|
||||
type: SCThingType.Dish,
|
||||
uid: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
};
|
||||
13
packages/core/test/dummy/not-a-dish.ts
Normal file
13
packages/core/test/dummy/not-a-dish.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import {SCThingOriginType} from '../../src/index.js';
|
||||
import {SCDish} from '../../lib/index.js';
|
||||
|
||||
export const notADish: Omit<SCDish, 'type'> & {type: 'foobar'} = {
|
||||
categories: ['appetizer'],
|
||||
name: 'foo',
|
||||
origin: {
|
||||
created: '',
|
||||
type: SCThingOriginType.User,
|
||||
},
|
||||
type: 'foobar',
|
||||
uid: 'bar',
|
||||
};
|
||||
18
packages/core/test/dummy/setting.ts
Normal file
18
packages/core/test/dummy/setting.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import {SCSetting, SCSettingInputType, SCThingOriginType, SCThingType} from '../../src/index.js';
|
||||
|
||||
export const setting: SCSetting = {
|
||||
categories: ['profile'],
|
||||
defaultValue: 'student',
|
||||
description: 'base-description',
|
||||
inputType: SCSettingInputType.SingleChoice,
|
||||
name: 'group',
|
||||
order: 1,
|
||||
origin: {
|
||||
indexed: '2018-11-11T14:30:00Z',
|
||||
name: 'Dummy',
|
||||
type: SCThingOriginType.Remote,
|
||||
},
|
||||
type: SCThingType.Setting,
|
||||
uid: '2c97aa36-4aa2-43de-bc5d-a2b2cb3a530e',
|
||||
values: ['student', 'employee', true, 42],
|
||||
};
|
||||
@@ -16,18 +16,17 @@ import {
|
||||
isLightweightClass,
|
||||
isLightweightEnum,
|
||||
isUnionType,
|
||||
} from '@openstapps/core-tools/lib/easy-ast/ast-util';
|
||||
import {LightweightAliasDefinition} from '@openstapps/core-tools/lib/easy-ast/types/lightweight-alias-definition';
|
||||
import {LightweightProjectWithIndex} from '@openstapps/core-tools/lib/easy-ast/types/lightweight-project';
|
||||
import {LightweightType} from '@openstapps/core-tools/lib/easy-ast/types/lightweight-type';
|
||||
import {LightweightClassDefinition} from '@openstapps/core-tools/src/easy-ast/types/lightweight-class-definition';
|
||||
import {LightweightDefinition} from '@openstapps/core-tools/src/easy-ast/types/lightweight-definition';
|
||||
import {LightweightProperty} from '@openstapps/core-tools/src/easy-ast/types/lightweight-property';
|
||||
LightweightAliasDefinition,
|
||||
LightweightProjectWithIndex,
|
||||
LightweightType,
|
||||
LightweightClassDefinition,
|
||||
LightweightDefinition,
|
||||
LightweightProperty,
|
||||
} from '@openstapps/easy-ast';
|
||||
import {expect} from 'chai';
|
||||
import {assign, chain, clone, flatMap, isNil, reduce, reject, some} from 'lodash';
|
||||
|
||||
process.on('unhandledRejection', err => {
|
||||
throw err;
|
||||
process.on('unhandledRejection', error => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
describe('Features', () => {
|
||||
@@ -37,8 +36,8 @@ describe('Features', () => {
|
||||
let thingsWithoutReferences: LightweightClassDefinition[];
|
||||
|
||||
before(function () {
|
||||
this.timeout(15000);
|
||||
this.slow(10000);
|
||||
this.timeout(15_000);
|
||||
this.slow(10_000);
|
||||
|
||||
project = new LightweightProjectWithIndex('src');
|
||||
|
||||
@@ -51,9 +50,7 @@ describe('Features', () => {
|
||||
referenceName: 'SCDiff',
|
||||
});
|
||||
|
||||
expect(
|
||||
thingsReflection.type?.specificationTypes?.every(it => typeof it.referenceName !== 'undefined'),
|
||||
).to.be.true;
|
||||
expect(thingsReflection.type?.specificationTypes?.map(it => it.referenceName)).not.to.include(undefined);
|
||||
thingNames = thingsReflection.type?.specificationTypes?.map(type => type.referenceName!) ?? [];
|
||||
things = thingNames.map(it => project.definitions[it]).filter(isLightweightClass);
|
||||
thingsWithoutReferences = thingNames
|
||||
@@ -64,15 +61,22 @@ describe('Features', () => {
|
||||
const inheritedProperties = function (
|
||||
classLike: LightweightClassDefinition,
|
||||
): Record<string, LightweightProperty> | undefined {
|
||||
return reduce(
|
||||
[...(classLike.implementedDefinitions ?? []), ...(classLike.extendedDefinitions ?? [])],
|
||||
(obj, extension) => {
|
||||
const object = project.definitions[extension.referenceName ?? ''];
|
||||
const extendClause = [
|
||||
...(classLike.implementedDefinitions ?? []),
|
||||
...(classLike.extendedDefinitions ?? []),
|
||||
];
|
||||
const properties = {...classLike.properties};
|
||||
|
||||
return assign(obj, isLightweightClass(object) ? inheritedProperties(object) : obj);
|
||||
},
|
||||
clone(classLike.properties),
|
||||
);
|
||||
for (const definition of extendClause) {
|
||||
const object = project.definitions[definition.referenceName!];
|
||||
if (isLightweightClass(object)) {
|
||||
Object.assign(properties, inheritedProperties(object));
|
||||
} else {
|
||||
Object.assign(properties, object);
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
};
|
||||
|
||||
it('should have an origin', () => {
|
||||
@@ -82,42 +86,36 @@ describe('Features', () => {
|
||||
});
|
||||
|
||||
it('should not have duplicate names', () => {
|
||||
reduce(
|
||||
project.files,
|
||||
(fileResult, file) =>
|
||||
reduce(
|
||||
file,
|
||||
(definitionResult, definition: LightweightDefinition) => {
|
||||
expect(definitionResult[definition.name]).to.be.undefined;
|
||||
definitionResult[definition.name] = true; // something that's not undefined
|
||||
const names = new Set<string>();
|
||||
|
||||
return definitionResult;
|
||||
},
|
||||
fileResult,
|
||||
),
|
||||
{} as Record<string, true>,
|
||||
);
|
||||
for (const fileName in project.files) {
|
||||
const file = project.files[fileName];
|
||||
for (const definition in file) {
|
||||
const definitionName = file[definition].name;
|
||||
expect(names).not.to.include(definitionName);
|
||||
names.add(definitionName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should not have properties referencing SCThing', () => {
|
||||
const allPropertyReferenceNames: (property: LightweightProperty) => string[] = property =>
|
||||
reject(
|
||||
[property.type.referenceName!, ...flatMap(property.properties, allPropertyReferenceNames)],
|
||||
isNil,
|
||||
);
|
||||
[
|
||||
property.type.referenceName!,
|
||||
...Object.values(property.properties ?? []).flatMap(allPropertyReferenceNames),
|
||||
].filter(it => !!it);
|
||||
|
||||
const typeHasSCThingReferences: (type?: LightweightType) => boolean = type =>
|
||||
type?.referenceName
|
||||
? hasSCThingReferences(project.definitions[type.referenceName])
|
||||
: some(type?.specificationTypes, typeHasSCThingReferences);
|
||||
: type?.specificationTypes?.some(typeHasSCThingReferences) === true;
|
||||
|
||||
const hasSCThingReferences: (definition?: LightweightDefinition) => boolean = definition =>
|
||||
isLightweightClass(definition)
|
||||
? chain(inheritedProperties(definition))
|
||||
.flatMap(it => flatMap(it.properties, allPropertyReferenceNames))
|
||||
? Object.values(inheritedProperties(definition) ?? [])
|
||||
.flatMap(it => Object.values(it.properties ?? []).flatMap(allPropertyReferenceNames))
|
||||
.map(it => project.definitions[it] as LightweightDefinition)
|
||||
.some(it => it.name === 'SCThing' || hasSCThingReferences(it))
|
||||
.value()
|
||||
: definition
|
||||
? typeHasSCThingReferences(definition.type)
|
||||
: false;
|
||||
@@ -127,16 +125,18 @@ describe('Features', () => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks if a definition is an SCThing
|
||||
*/
|
||||
function extendsSCThing(definition?: LightweightDefinition): boolean {
|
||||
return isLightweightClass(definition)
|
||||
? chain([
|
||||
? [
|
||||
...((definition as LightweightClassDefinition).extendedDefinitions ?? []),
|
||||
...((definition as LightweightClassDefinition).implementedDefinitions ?? []),
|
||||
])
|
||||
]
|
||||
.map(it => it.referenceName)
|
||||
.reject(isNil)
|
||||
.filter(it => !!it)
|
||||
.some(it => it === 'SCThing' || extendsSCThing(project.definitions[it!]))
|
||||
.value()
|
||||
: false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable unicorn/no-null */
|
||||
/*
|
||||
* Copyright (C) 2018, 2019 StApps
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
@@ -12,12 +13,7 @@
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||
import {SCBulkResponse} from '../src/protocol/routes/bulk-request.js';
|
||||
import {SCMultiSearchResponse} from '../src/protocol/routes/search-multi.js';
|
||||
import {SCSearchResponse} from '../src/protocol/routes/search.js';
|
||||
import {SCThingOriginType, SCThingType} from '../src/things/abstract/thing.js';
|
||||
import {SCDish} from '../src/things/dish.js';
|
||||
import {SCMultiSearchResponse} from '../src/index.js';
|
||||
import {expect} from 'chai';
|
||||
import {
|
||||
isBulkResponse,
|
||||
@@ -26,117 +22,104 @@ import {
|
||||
isThing,
|
||||
isThingWithTranslations,
|
||||
} from '../src/guards.js';
|
||||
import {bulkResponse} from './dummy/bulk-response.js';
|
||||
import {dishWithTranslation} from './dummy/dish-with-translation.js';
|
||||
import {dishWithTranslationSearchResponse} from './dummy/dish-with-translation-search-response.js';
|
||||
import {notADish} from './dummy/not-a-dish.js';
|
||||
import {SCBulkResponse} from '../src/protocol/routes/bulk-request.js';
|
||||
import {SCSearchResponse} from '../src/protocol/routes/search.js';
|
||||
import {SCMultiSearchResponse} from '../src/protocol/routes/search-multi.js';
|
||||
import {SCThingOriginType, SCThingType} from '../src/things/abstract/thing.js';
|
||||
import {SCDish} from '../src/things/dish';
|
||||
import {SCDish} from '../src/things/dish.js';
|
||||
|
||||
@suite(timeout(10000), slow(5000))
|
||||
export class GuardsSpec {
|
||||
static bulkResponse: SCBulkResponse = {
|
||||
expiration: '2009-06-30T18:30:00+02:00 ',
|
||||
source: 'bar',
|
||||
state: 'done',
|
||||
type: SCThingType.Dish,
|
||||
uid: 'foo',
|
||||
};
|
||||
describe('Guards', function () {
|
||||
this.timeout(10_000);
|
||||
this.slow(5000);
|
||||
|
||||
static dishWithTranslation: SCDish = {
|
||||
categories: ['appetizer'],
|
||||
name: 'foo',
|
||||
origin: {
|
||||
created: '',
|
||||
type: SCThingOriginType.User,
|
||||
},
|
||||
translations: {
|
||||
de: {
|
||||
name: 'Foo',
|
||||
},
|
||||
},
|
||||
type: SCThingType.Dish,
|
||||
uid: 'bar',
|
||||
};
|
||||
describe('isBulkResponse', function () {
|
||||
it(`should not accept nullish values`, function () {
|
||||
expect(isBulkResponse(null)).to.be.false;
|
||||
});
|
||||
|
||||
static notADish = {
|
||||
categories: ['appetizer'],
|
||||
name: 'foo',
|
||||
origin: {
|
||||
created: '',
|
||||
type: SCThingOriginType.User,
|
||||
},
|
||||
type: 'foobar',
|
||||
uid: 'bar',
|
||||
};
|
||||
it('should not accept a dish', function () {
|
||||
expect(isBulkResponse(dishWithTranslation)).to.be.false;
|
||||
});
|
||||
|
||||
static searchResponse: SCSearchResponse = {
|
||||
data: [GuardsSpec.dishWithTranslation],
|
||||
facets: [
|
||||
{
|
||||
buckets: [
|
||||
{
|
||||
count: 1,
|
||||
key: 'key',
|
||||
},
|
||||
],
|
||||
field: 'field',
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
count: 1,
|
||||
offset: 0,
|
||||
total: 1,
|
||||
},
|
||||
stats: {
|
||||
time: 1,
|
||||
},
|
||||
};
|
||||
it('should accept a bulk', function () {
|
||||
expect(isBulkResponse(bulkResponse)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
@test
|
||||
public isBulkResponse() {
|
||||
expect(isBulkResponse(null)).to.be.equal(false);
|
||||
expect(isBulkResponse(GuardsSpec.dishWithTranslation)).to.be.equal(false);
|
||||
expect(isBulkResponse(GuardsSpec.bulkResponse)).to.be.equal(true);
|
||||
}
|
||||
|
||||
@test
|
||||
public isMultiSearchResponse() {
|
||||
describe('isMultiSearchResponse', function () {
|
||||
const multiSearchResponse: SCMultiSearchResponse = {
|
||||
foo: GuardsSpec.searchResponse,
|
||||
foo: dishWithTranslationSearchResponse,
|
||||
};
|
||||
expect(isMultiSearchResponse(multiSearchResponse)).to.be.equal(true);
|
||||
const notAMultiSearchResponse = {...multiSearchResponse, ...{bar: 'baz'}};
|
||||
expect(isMultiSearchResponse(notAMultiSearchResponse)).to.be.equal(false);
|
||||
delete multiSearchResponse.foo;
|
||||
expect(isMultiSearchResponse(multiSearchResponse)).to.be.equal(false);
|
||||
}
|
||||
|
||||
@test
|
||||
public isSearchResponse() {
|
||||
const notASearchResponse = {...GuardsSpec.searchResponse};
|
||||
// @ts-ignore
|
||||
delete notASearchResponse.pagination;
|
||||
expect(isSearchResponse(notASearchResponse)).to.be.equal(false);
|
||||
// @ts-ignore
|
||||
delete notASearchResponse.data;
|
||||
expect(isSearchResponse(notASearchResponse)).to.be.equal(false);
|
||||
expect(isSearchResponse(null)).to.be.equal(false);
|
||||
expect(isSearchResponse(GuardsSpec.searchResponse)).to.be.equal(true);
|
||||
}
|
||||
it('should accept a multi search response', function () {
|
||||
expect(isMultiSearchResponse(multiSearchResponse)).to.be.true;
|
||||
});
|
||||
|
||||
@test
|
||||
public isThing() {
|
||||
expect(isThing('foo')).to.be.equal(false);
|
||||
expect(isThing({type: 'foo'})).to.be.equal(false);
|
||||
expect(isThing(GuardsSpec.notADish)).to.be.equal(false);
|
||||
expect(isThing(GuardsSpec.dishWithTranslation)).to.be.equal(true);
|
||||
}
|
||||
it('should not accept a multi search response with invalid search requests', function () {
|
||||
const notAMultiSearchResponse = {...multiSearchResponse, bar: 'baz'};
|
||||
expect(isMultiSearchResponse(notAMultiSearchResponse)).to.be.false;
|
||||
});
|
||||
|
||||
@test
|
||||
public isThingWithTranslations() {
|
||||
const dishWithoutTranslation = {...GuardsSpec.dishWithTranslation};
|
||||
delete dishWithoutTranslation.translations;
|
||||
expect(isThingWithTranslations(dishWithoutTranslation)).to.be.equal(false);
|
||||
expect(isThingWithTranslations(GuardsSpec.dishWithTranslation)).to.be.equal(true);
|
||||
}
|
||||
}
|
||||
it('should not accept empty responses', function () {
|
||||
expect(isMultiSearchResponse({})).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSearchResponse', function () {
|
||||
it('should accept a search response', function () {
|
||||
expect(isSearchResponse(dishWithTranslationSearchResponse)).to.be.true;
|
||||
});
|
||||
|
||||
it('should not accept nullish values', function () {
|
||||
expect(isSearchResponse(null)).to.be.false;
|
||||
});
|
||||
|
||||
it('should not accept a response without pagination', function () {
|
||||
const response = {...dishWithTranslationSearchResponse};
|
||||
// @ts-expect-error this is on purpose of course
|
||||
delete response.pagination;
|
||||
expect(isSearchResponse(response)).to.be.false;
|
||||
});
|
||||
|
||||
it('should not accept a response without data', function () {
|
||||
const response = {...dishWithTranslationSearchResponse};
|
||||
// @ts-expect-error this is on purpose of course
|
||||
delete response.data;
|
||||
expect(isSearchResponse(response)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('isThing', function () {
|
||||
it('should not accept strings', function () {
|
||||
expect(isThing('foo')).to.be.false;
|
||||
});
|
||||
|
||||
it('should not accept objects with arbitrary type values', function () {
|
||||
expect(isThing({type: 'foo'})).to.be.false;
|
||||
});
|
||||
|
||||
it('should not accept things with missing props', function () {
|
||||
expect(isThing(notADish)).to.be.false;
|
||||
});
|
||||
|
||||
it('should accept valid things', function () {
|
||||
expect(isThing(dishWithTranslation)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('isThingWithTranslations', function () {
|
||||
it('should not accept things without translations', function () {
|
||||
const dishWithoutTranslation = {...dishWithTranslation};
|
||||
delete dishWithoutTranslation.translations;
|
||||
expect(isThingWithTranslations(dishWithoutTranslation)).to.be.false;
|
||||
});
|
||||
|
||||
it('should accept things with translations', function () {
|
||||
expect(isThingWithTranslations(dishWithTranslation)).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,69 +14,51 @@
|
||||
*/
|
||||
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||
import {expect} from 'chai';
|
||||
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||
import {SCBulkRoute} from '../src/protocol/routes/bulk-request.js';
|
||||
import {SCBulkAddRoute} from '../src/protocol/routes/bulk-add.js';
|
||||
import {SCThingUpdateRoute} from '../src/protocol/routes/thing-update.js';
|
||||
import {SCBulkRoute} from '../src/index.js';
|
||||
import {SCBulkAddRoute} from '../src/index.js';
|
||||
import {SCThingUpdateRoute} from '../src/index.js';
|
||||
|
||||
@suite(timeout(10000), slow(5000))
|
||||
export class RoutesSpec {
|
||||
@test
|
||||
public bulkAddRouteUrlPath() {
|
||||
const bulkAddRoute = new SCBulkAddRoute();
|
||||
describe('Routes', function () {
|
||||
this.timeout(10_000);
|
||||
this.slow(5000);
|
||||
|
||||
it('should produce correct BulkAddRoute url path', function () {
|
||||
expect(
|
||||
bulkAddRoute.getUrlPath({
|
||||
new SCBulkAddRoute().getUrlPath({
|
||||
UID: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
}),
|
||||
).to.equal('/bulk/540862f3-ea30-5b8f-8678-56b4dc217140');
|
||||
}
|
||||
});
|
||||
|
||||
@test
|
||||
public bulkRouteUrlPath() {
|
||||
const bulkRoute = new SCBulkRoute();
|
||||
|
||||
expect(bulkRoute.getUrlPath()).to.equal('/bulk');
|
||||
}
|
||||
|
||||
@test
|
||||
public thingUpdateRouteUrlPath() {
|
||||
const thingUpdateRoute = new SCThingUpdateRoute();
|
||||
it('should produce correct BlukRoute url path', function () {
|
||||
expect(new SCBulkRoute().getUrlPath()).to.equal('/bulk');
|
||||
});
|
||||
|
||||
it('should produce correct ThingUpdateRoute url path', function () {
|
||||
expect(
|
||||
thingUpdateRoute.getUrlPath({
|
||||
new SCThingUpdateRoute().getUrlPath({
|
||||
TYPE: 'dish',
|
||||
UID: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
}),
|
||||
).to.equal('/dish/540862f3-ea30-5b8f-8678-56b4dc217140');
|
||||
}
|
||||
});
|
||||
|
||||
@test
|
||||
public tooManyParameters() {
|
||||
const thingUpdateRoute = new SCThingUpdateRoute();
|
||||
|
||||
const fn = () => {
|
||||
thingUpdateRoute.getUrlPath({
|
||||
it('should throw an error if too many parameters are provided', function () {
|
||||
expect(() =>
|
||||
new SCThingUpdateRoute().getUrlPath({
|
||||
FOO: 'bar',
|
||||
TYPE: 'dish',
|
||||
UID: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
});
|
||||
};
|
||||
}),
|
||||
).to.throw('Extraneous parameters provided.');
|
||||
});
|
||||
|
||||
expect(fn).to.throw('Extraneous parameters provided.');
|
||||
}
|
||||
|
||||
@test
|
||||
public wrongParameters() {
|
||||
const thingUpdateRoute = new SCThingUpdateRoute();
|
||||
|
||||
const fn = () => {
|
||||
thingUpdateRoute.getUrlPath({
|
||||
it('should throw an error if wrong parameters are provided', function () {
|
||||
expect(() =>
|
||||
new SCThingUpdateRoute().getUrlPath({
|
||||
TYPO: 'dish',
|
||||
UID: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
});
|
||||
};
|
||||
|
||||
expect(fn).to.throw("Parameter 'TYPE' not provided.");
|
||||
}
|
||||
}
|
||||
}),
|
||||
).to.throw("Parameter 'TYPE' not provided.");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
import {validateFiles, writeReport} from '@openstapps/core-tools/lib/validate';
|
||||
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||
import {validateFiles, writeReport} from '@openstapps/core-tools';
|
||||
import {expect} from 'chai';
|
||||
import {mkdirSync} from 'fs';
|
||||
import {join, resolve} from 'path';
|
||||
import {mkdir} from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
@suite(timeout(15000), slow(10000))
|
||||
export class SchemaSpec {
|
||||
@test
|
||||
async 'validate against test files'() {
|
||||
const errorsPerFile = {
|
||||
...(await validateFiles(resolve('lib', 'schema'), resolve('test', 'resources'))),
|
||||
...(await validateFiles(resolve('lib', 'schema'), resolve('test', 'resources', 'indexable'))),
|
||||
};
|
||||
describe('Schema', function () {
|
||||
this.timeout(15_000);
|
||||
this.slow(10_000);
|
||||
|
||||
let unexpected = false;
|
||||
Object.keys(errorsPerFile).forEach(file => {
|
||||
unexpected = unexpected || errorsPerFile[file].some(error => !error.expected);
|
||||
});
|
||||
it('should validate against test files', async function () {
|
||||
const errorsPerFile = await validateFiles(path.resolve('lib', 'schema'), path.resolve('test', 'resources'));
|
||||
|
||||
mkdirSync('report', {
|
||||
recursive: true,
|
||||
});
|
||||
await mkdir('report', {recursive: true});
|
||||
await writeReport(path.join('report', 'index.html'), errorsPerFile);
|
||||
|
||||
await writeReport(join('report', 'index.html'), errorsPerFile);
|
||||
|
||||
expect(unexpected).to.be.equal(false);
|
||||
}
|
||||
}
|
||||
for (const file of Object.keys(errorsPerFile)) {
|
||||
for (const error of errorsPerFile[file]) {
|
||||
expect(error.expected).to.be.true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,93 +15,11 @@
|
||||
import {slow, suite, test, timeout} from '@testdeck/mocha';
|
||||
import {expect} from 'chai';
|
||||
import clone from 'rfdc';
|
||||
import {SCThingOriginType, SCThingRemoteOrigin, SCThingType} from '../src/things/abstract/thing.js';
|
||||
import {SCBuildingWithoutReferences} from '../src/things/building.js';
|
||||
import {SCDish, SCDishMeta} from '../src/things/dish.js';
|
||||
import {SCSetting, SCSettingInputType} from '../src/things/setting.js';
|
||||
import {SCThingTranslator} from '../src/translator.js';
|
||||
|
||||
const building: SCBuildingWithoutReferences = {
|
||||
address: {
|
||||
addressCountry: 'base-address.addressCountry',
|
||||
addressLocality: 'base-address.addressLocality',
|
||||
postalCode: 'base-address.postalCode',
|
||||
streetAddress: 'base-address.streetAddress',
|
||||
},
|
||||
categories: ['office', 'education'],
|
||||
floors: ['base-floor0', 'base-floor1'],
|
||||
geo: {
|
||||
point: {
|
||||
coordinates: [12.0, 13.0],
|
||||
type: 'Point',
|
||||
},
|
||||
},
|
||||
name: 'base-space-name',
|
||||
translations: {
|
||||
de: {
|
||||
address: {
|
||||
addressCountry: 'de-address.addressCountry',
|
||||
addressLocality: 'de-address.addressLocality',
|
||||
postalCode: 'de-address.postalCode',
|
||||
streetAddress: 'de-address.streetAddress',
|
||||
},
|
||||
floors: ['de-floor0', 'de-floor1'],
|
||||
name: 'de-space-name',
|
||||
},
|
||||
},
|
||||
type: SCThingType.Building,
|
||||
uid: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
};
|
||||
|
||||
const dish: SCDish = {
|
||||
categories: ['main dish', 'dessert'],
|
||||
characteristics: [{name: 'base-characteristic0'}, {name: 'base-characteristic1'}],
|
||||
name: 'base-dish-name',
|
||||
offers: [
|
||||
{
|
||||
availability: 'in stock',
|
||||
inPlace: building,
|
||||
prices: {
|
||||
default: 23.42,
|
||||
},
|
||||
provider: {
|
||||
name: 'base-provider',
|
||||
type: SCThingType.Organization,
|
||||
uid: '540862f3-ea30-5b8f-8678-56b4dc217141',
|
||||
},
|
||||
},
|
||||
],
|
||||
origin: {
|
||||
indexed: '1970-01-01T00:00:00.000Z',
|
||||
name: 'dish-connector',
|
||||
type: SCThingOriginType.Remote,
|
||||
},
|
||||
translations: {
|
||||
de: {
|
||||
characteristics: [{name: 'de-characteristic0'}, {name: 'de-characteristic1'}],
|
||||
name: 'de-dish-name',
|
||||
},
|
||||
},
|
||||
type: SCThingType.Dish,
|
||||
uid: '540862f3-ea30-5b8f-8678-56b4dc217140',
|
||||
};
|
||||
|
||||
const setting: SCSetting = {
|
||||
categories: ['profile'],
|
||||
defaultValue: 'student',
|
||||
description: 'base-description',
|
||||
inputType: SCSettingInputType.SingleChoice,
|
||||
name: 'group',
|
||||
order: 1,
|
||||
origin: {
|
||||
indexed: '2018-11-11T14:30:00Z',
|
||||
name: 'Dummy',
|
||||
type: SCThingOriginType.Remote,
|
||||
},
|
||||
type: SCThingType.Setting,
|
||||
uid: '2c97aa36-4aa2-43de-bc5d-a2b2cb3a530e',
|
||||
values: ['student', 'employee', true, 42],
|
||||
};
|
||||
import {SCThingRemoteOrigin} from '../src/index.js';
|
||||
import {SCDishMeta} from '../src/index.js';
|
||||
import {SCThingTranslator} from '../src/index.js';
|
||||
import {dish} from './dummy/dish.js';
|
||||
import {setting} from './dummy/setting.js';
|
||||
|
||||
const translator = new SCThingTranslator('de');
|
||||
const translatorEN = new SCThingTranslator('en');
|
||||
@@ -111,242 +29,207 @@ const translatorWithFallback = new SCThingTranslator('tt');
|
||||
const translatedThingDE = translator.translate(dish);
|
||||
const translatedThingFallback = translatorWithFallback.translate(dish);
|
||||
|
||||
@suite(timeout(10000), slow(5000))
|
||||
export class TranslationSpecInplace {
|
||||
@test
|
||||
public directEnumSingleValue() {
|
||||
expect(translator.translatedAccess(setting).inputType()).to.equal('einfache Auswahl');
|
||||
}
|
||||
describe('Translator', function () {
|
||||
this.timeout(10_000);
|
||||
this.slow(5000);
|
||||
|
||||
@test
|
||||
public directStringLiteralType() {
|
||||
expect(translator.translatedAccess(dish).type()).to.equal('Essen');
|
||||
expect(translatedThingDE.type).to.equal('Essen');
|
||||
}
|
||||
|
||||
@test
|
||||
public directStringProperty() {
|
||||
expect(translator.translatedAccess(dish).name()).to.equal('de-dish-name');
|
||||
expect(translatedThingDE.name).to.equal('de-dish-name');
|
||||
}
|
||||
|
||||
@test
|
||||
public directArrayOfString() {
|
||||
expect(translator.translatedAccess(dish).characteristics()).to.deep.equal([
|
||||
{name: 'de-characteristic0'},
|
||||
{name: 'de-characteristic1'},
|
||||
]);
|
||||
expect(translatedThingDE.characteristics).to.deep.equal([
|
||||
{name: 'de-characteristic0'},
|
||||
{name: 'de-characteristic1'},
|
||||
]);
|
||||
}
|
||||
|
||||
@test
|
||||
public directArrayOfStringSubscript() {
|
||||
expect(translator.translatedAccess(dish).characteristics[1]()).to.deep.equal({
|
||||
name: 'de-characteristic1',
|
||||
describe('direct', function () {
|
||||
it('should translate enum single value', function () {
|
||||
expect(translator.translatedAccess(setting).inputType).to.equal('einfache Auswahl');
|
||||
});
|
||||
expect(translatedThingDE.characteristics![1]).to.deep.equal({name: 'de-characteristic1'});
|
||||
}
|
||||
|
||||
@test
|
||||
public directMetaArrayOfString() {
|
||||
expect(translator.translatedAccess(dish).categories()).to.deep.equal(['Hauptgericht', 'Nachtisch']);
|
||||
expect(translatedThingDE.categories).to.deep.equal(['Hauptgericht', 'Nachtisch']);
|
||||
}
|
||||
|
||||
@test
|
||||
public directMetaArrayOfStringSubscript() {
|
||||
expect(translator.translatedAccess(dish).categories[1]()).to.equal('Nachtisch');
|
||||
expect(translatedThingDE.categories[1]).to.equal('Nachtisch');
|
||||
}
|
||||
|
||||
@test
|
||||
public nestedStringLiteralType() {
|
||||
expect(translator.translatedAccess(dish).offers[0].inPlace.type()).to.equal('Gebäude');
|
||||
expect(translatedThingDE.offers![0].inPlace!.type).to.equal('Gebäude');
|
||||
}
|
||||
|
||||
@test
|
||||
public nestedStringProperty() {
|
||||
expect(translator.translatedAccess(dish).offers[0].inPlace.name()).to.equal('de-space-name');
|
||||
expect(translatedThingDE.offers![0].inPlace!.name).to.equal('de-space-name');
|
||||
}
|
||||
|
||||
@test
|
||||
public nestedMetaArrayOfString() {
|
||||
expect(translator.translatedAccess(dish).offers[0].inPlace.categories()).to.deep.equal([
|
||||
'Büro',
|
||||
'Bildung',
|
||||
]);
|
||||
expect(translatedThingDE.offers![0].inPlace!.categories).to.deep.equal(['Büro', 'Bildung']);
|
||||
}
|
||||
|
||||
@test
|
||||
public nestedMetaArrayOfStringSubscript() {
|
||||
expect(translator.translatedAccess(dish).offers[0].inPlace.categories[1]()).to.equal('Bildung');
|
||||
expect(translatedThingDE.offers![0].inPlace!.categories[1]).to.equal('Bildung');
|
||||
}
|
||||
|
||||
@test
|
||||
public directStringLiteralTypeFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).type()).to.equal('dish');
|
||||
expect(translatedThingFallback.type).to.equal('dish');
|
||||
}
|
||||
|
||||
@test
|
||||
public directStringPropertyFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).name()).to.equal('base-dish-name');
|
||||
expect(translatedThingFallback.name).to.equal('base-dish-name');
|
||||
}
|
||||
|
||||
@test
|
||||
public directArrayOfStringSubscriptFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).characteristics[1]()).to.deep.equal({
|
||||
name: 'base-characteristic1',
|
||||
it('should translate string literal type', function () {
|
||||
expect(translator.translatedAccess(dish).type).to.equal('Essen');
|
||||
expect(translatedThingDE.type).to.equal('Essen');
|
||||
});
|
||||
expect(translatedThingFallback.characteristics![1]).to.deep.equal({name: 'base-characteristic1'});
|
||||
}
|
||||
|
||||
@test
|
||||
public directMetaArrayOfStringFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).categories()).to.deep.equal([
|
||||
'main dish',
|
||||
'dessert',
|
||||
]);
|
||||
expect(translatedThingFallback.categories).to.deep.equal(['main dish', 'dessert']);
|
||||
}
|
||||
it('should translate string property', function () {
|
||||
expect(translator.translatedAccess(dish).name).to.equal('de-dish-name');
|
||||
expect(translatedThingDE.name).to.equal('de-dish-name');
|
||||
});
|
||||
|
||||
@test
|
||||
public directMetaArrayOfStringSubscriptFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).categories[1]()).to.equal('dessert');
|
||||
expect(translatedThingFallback.categories[1]).to.equal('dessert');
|
||||
}
|
||||
it('should translate array of strings', function () {
|
||||
expect(translator.translatedAccess(dish).characteristics).to.deep.equal([
|
||||
{name: 'de-characteristic0'},
|
||||
{name: 'de-characteristic1'},
|
||||
]);
|
||||
expect(translatedThingDE.characteristics).to.deep.equal([
|
||||
{name: 'de-characteristic0'},
|
||||
{name: 'de-characteristic1'},
|
||||
]);
|
||||
});
|
||||
|
||||
@test
|
||||
public nestedStringLiteralTypeFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers[0].inPlace.type()).to.equal('building');
|
||||
expect(translatedThingFallback.offers![0].inPlace!.type).to.equal('building');
|
||||
}
|
||||
it('should translate array of strings subscript', function () {
|
||||
expect(translator.translatedAccess(dish).characteristics?.[1]).to.deep.equal({
|
||||
name: 'de-characteristic1',
|
||||
});
|
||||
expect(translatedThingDE.characteristics![1]).to.deep.equal({name: 'de-characteristic1'});
|
||||
});
|
||||
|
||||
@test
|
||||
public nestedStringPropertyFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers[0].inPlace.name()).to.equal(
|
||||
'base-space-name',
|
||||
);
|
||||
expect(translatedThingFallback.offers![0].inPlace!.name).to.equal('base-space-name');
|
||||
}
|
||||
it('should translate meta array of string', function () {
|
||||
expect(translator.translatedAccess(dish).categories).to.deep.equal(['Hauptgericht', 'Nachtisch']);
|
||||
expect(translatedThingDE.categories).to.deep.equal(['Hauptgericht', 'Nachtisch']);
|
||||
});
|
||||
|
||||
@test
|
||||
public nestedMetaArrayOfStringFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers[0].inPlace.categories()).to.deep.equal([
|
||||
'office',
|
||||
'education',
|
||||
]);
|
||||
expect(translatedThingFallback.offers![0].inPlace!.categories).to.deep.equal(['office', 'education']);
|
||||
}
|
||||
it('should translate meta array of strings subscript', function () {
|
||||
expect(translator.translatedAccess(dish).categories[1]).to.equal('Nachtisch');
|
||||
expect(translatedThingDE.categories[1]).to.equal('Nachtisch');
|
||||
});
|
||||
});
|
||||
|
||||
@test
|
||||
public nestedMetaArrayOfStringSubscriptFallback() {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers[0].inPlace.categories[1]()).to.equal(
|
||||
'education',
|
||||
);
|
||||
expect(translatedThingFallback.offers![0].inPlace!.categories[1]).to.equal('education');
|
||||
}
|
||||
describe('nested', function () {
|
||||
it('should translate string literal type', function () {
|
||||
expect(translator.translatedAccess(dish).offers?.[0].inPlace?.type).to.equal('Gebäude');
|
||||
expect(translatedThingDE.offers![0].inPlace!.type).to.equal('Gebäude');
|
||||
});
|
||||
|
||||
@test
|
||||
public directStringLiteralTypeUndefined() {
|
||||
const undefinedThing = eval('(x) => undefined;');
|
||||
expect(translator.translatedAccess(undefinedThing())('defaultValue')).to.equal('defaultValue');
|
||||
expect(translator.translatedAccess(dish).name('defaultValue')).to.not.equal('defaultValue');
|
||||
}
|
||||
it('should translate nested string property', function () {
|
||||
expect(translator.translatedAccess(dish).offers?.[0].inPlace?.name).to.equal('de-space-name');
|
||||
expect(translatedThingDE.offers![0].inPlace!.name).to.equal('de-space-name');
|
||||
});
|
||||
|
||||
@test
|
||||
public nestedMetaArrayOfStringSubscriptUndefined() {
|
||||
const workingTranslation = eval(
|
||||
"translator.translatedAccess(dish).offers[0].inPlace.categories[1]('printer');",
|
||||
);
|
||||
const defaultValueTranslation = eval(
|
||||
"translator.translatedAccess(dish).offers[0].inPlace.categories[1234]('printer');",
|
||||
);
|
||||
it('should translate meta array of strings', function () {
|
||||
expect(translator.translatedAccess(dish).offers?.[0].inPlace?.categories).to.deep.equal([
|
||||
'Büro',
|
||||
'Bildung',
|
||||
]);
|
||||
expect(translatedThingDE.offers![0].inPlace!.categories).to.deep.equal(['Büro', 'Bildung']);
|
||||
});
|
||||
|
||||
expect(defaultValueTranslation).to.equal('printer');
|
||||
expect(workingTranslation).to.not.equal('printer');
|
||||
}
|
||||
it('should translate meta array of strings subscript', function () {
|
||||
expect(translator.translatedAccess(dish).offers?.[0].inPlace?.categories[1]).to.equal('Bildung');
|
||||
expect(translatedThingDE.offers![0].inPlace!.categories[1]).to.equal('Bildung');
|
||||
});
|
||||
});
|
||||
|
||||
@test
|
||||
public reaccessWithChangedSourceOmitsLRUCache() {
|
||||
describe('direct (fallback)', function () {
|
||||
it('should translate string literal types', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).type).to.equal('dish');
|
||||
expect(translatedThingFallback.type).to.equal('dish');
|
||||
});
|
||||
|
||||
it('should translate string property', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).name).to.equal('base-dish-name');
|
||||
expect(translatedThingFallback.name).to.equal('base-dish-name');
|
||||
});
|
||||
|
||||
it('should translate array of strings subscript', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).characteristics?.[1]).to.deep.equal({
|
||||
name: 'base-characteristic1',
|
||||
});
|
||||
expect(translatedThingFallback.characteristics![1]).to.deep.equal({name: 'base-characteristic1'});
|
||||
});
|
||||
|
||||
it('should translate meta array of strings', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).categories).to.deep.equal([
|
||||
'main dish',
|
||||
'dessert',
|
||||
]);
|
||||
expect(translatedThingFallback.categories).to.deep.equal(['main dish', 'dessert']);
|
||||
});
|
||||
|
||||
it('should translate meta array of string subscript', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).categories[1]).to.equal('dessert');
|
||||
expect(translatedThingFallback.categories[1]).to.equal('dessert');
|
||||
});
|
||||
});
|
||||
|
||||
describe('nested (fallback)', function () {
|
||||
it('should translate string literal type', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers?.[0].inPlace?.type).to.equal('building');
|
||||
expect(translatedThingFallback.offers![0].inPlace!.type).to.equal('building');
|
||||
});
|
||||
|
||||
it('should translate string property', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers?.[0].inPlace?.name).to.equal(
|
||||
'base-space-name',
|
||||
);
|
||||
expect(translatedThingFallback.offers![0].inPlace!.name).to.equal('base-space-name');
|
||||
});
|
||||
|
||||
it('should translate meta array of string', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers?.[0].inPlace?.categories).to.deep.equal([
|
||||
'office',
|
||||
'education',
|
||||
]);
|
||||
expect(translatedThingFallback.offers![0].inPlace!.categories).to.deep.equal(['office', 'education']);
|
||||
});
|
||||
|
||||
it('should translate meta array of strings subscript', function () {
|
||||
expect(translatorWithFallback.translatedAccess(dish).offers?.[0].inPlace?.categories[1]).to.equal(
|
||||
'education',
|
||||
);
|
||||
expect(translatedThingFallback.offers![0].inPlace!.categories[1]).to.equal('education');
|
||||
});
|
||||
});
|
||||
|
||||
it('should omit LRU cache with changed source', function () {
|
||||
const translatorDE = new SCThingTranslator('de');
|
||||
const dishCopy = clone()(dish);
|
||||
const translatedDish = translatorDE.translatedAccess(dish);
|
||||
const distructivelyTranslatedDish = translatorDE.translate(dish);
|
||||
const destructivelyTranslatedDish = translatorDE.translate(dish);
|
||||
|
||||
(dishCopy.origin as SCThingRemoteOrigin).name = 'tranlator.spec';
|
||||
(dishCopy.origin as SCThingRemoteOrigin).name = 'translator.spec';
|
||||
expect(translatorDE.translatedAccess(dishCopy)).not.to.deep.equal(translatedDish);
|
||||
expect(translatorDE.translate(dishCopy)).not.to.equal(distructivelyTranslatedDish);
|
||||
}
|
||||
expect(translatorDE.translate(dishCopy)).not.to.equal(destructivelyTranslatedDish);
|
||||
});
|
||||
|
||||
@test
|
||||
public changingTranslatorLanguageFlushesItsLRUCache() {
|
||||
it('should flush its LRU cache with changed translator language', function () {
|
||||
const translatorDE = new SCThingTranslator('de');
|
||||
expect(translatorDE.translatedAccess(dish).name()).to.equal('de-dish-name');
|
||||
expect(translatorDE.translatedAccess(dish).name).to.equal('de-dish-name');
|
||||
expect(translatorDE.translate(dish).name).to.equal('de-dish-name');
|
||||
translatorDE.language = 'en';
|
||||
expect(translatorDE.translatedAccess(dish).name()).to.equal('base-dish-name');
|
||||
expect(translatorDE.translatedAccess(dish).name).to.equal('base-dish-name');
|
||||
expect(translatorDE.translate(dish).name).to.equal('base-dish-name');
|
||||
}
|
||||
});
|
||||
|
||||
@test
|
||||
public forceTranslatorLRUCacheToOverflow() {
|
||||
it('should force translator LRU cache to overflow', function () {
|
||||
const translatorDE = new SCThingTranslator('de');
|
||||
// Make sure to add more elements to the translator cache than the maximum cache capacity. See Translator.ts
|
||||
for (let i = 0; i < 201; i++) {
|
||||
const anotherDish = Object.assign({}, dish);
|
||||
anotherDish.uid = String(i);
|
||||
expect(translatorDE.translatedAccess(anotherDish).name()).to.equal('de-dish-name');
|
||||
expect(translatorDE.translatedAccess(anotherDish).name).to.equal('de-dish-name');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@suite(timeout(10000), slow(5000))
|
||||
export class MetaTranslationSpec {
|
||||
@test
|
||||
public consistencyWithMetaClass() {
|
||||
describe('MetaTranslator', function () {
|
||||
this.timeout(10_000);
|
||||
this.slow(5000);
|
||||
|
||||
it('should have consistency with meta class', function () {
|
||||
const dishMetaTranslationsDE = translator.translatedPropertyNames(dish.type);
|
||||
const dishMetaTranslationsEN = translatorEN.translatedPropertyNames(dish.type);
|
||||
expect(dishMetaTranslationsEN).to.not.deep.equal(dishMetaTranslationsDE);
|
||||
expect(dishMetaTranslationsDE).to.deep.equal(new SCDishMeta().fieldTranslations.de);
|
||||
expect(dishMetaTranslationsEN).to.deep.equal(new SCDishMeta().fieldTranslations.en);
|
||||
}
|
||||
});
|
||||
|
||||
@test
|
||||
public retrieveTranslatedPropertyValueType() {
|
||||
it('should retrieve translated property value type', function () {
|
||||
const dishTypeDE = translator.translatedPropertyValue(dish.type, 'type');
|
||||
const dishTypeEN = translatorEN.translatedPropertyValue(dish.type, 'type', undefined);
|
||||
const dishTypeBASE = translatorWithFallback.translatedPropertyValue(dish.type, 'type');
|
||||
expect(dishTypeDE).to.deep.equal(new SCDishMeta().fieldValueTranslations.de.type);
|
||||
expect(dishTypeEN).to.deep.equal(new SCDishMeta().fieldValueTranslations.en.type);
|
||||
expect(dishTypeBASE).to.deep.equal(new SCDishMeta().fieldValueTranslations.en.type);
|
||||
}
|
||||
});
|
||||
|
||||
@test
|
||||
public retrieveTranslatedPropertyValueNested() {
|
||||
it('should retrieve translated property value nested', function () {
|
||||
const dishTypeDE = translator.translatedPropertyValue(dish.type, 'categories', 'main dish');
|
||||
const dishTypeEN = translatorEN.translatedPropertyValue(dish.type, 'categories', 'main dish');
|
||||
const dishTypeBASE = translatorWithFallback.translatedPropertyValue(dish.type, 'categories', 'main dish');
|
||||
expect(dishTypeDE).to.deep.equal(new SCDishMeta().fieldValueTranslations.de.categories['main dish']);
|
||||
expect(dishTypeEN).to.deep.equal(dish.categories[0]);
|
||||
expect(dishTypeBASE).to.deep.equal(dish.categories[0]);
|
||||
}
|
||||
});
|
||||
|
||||
@test
|
||||
public thingWithoutMetaClass() {
|
||||
it('should translate thing without meta class', function () {
|
||||
const dishCopy = clone()(dish);
|
||||
const typeNonExistant = eval("(x) => x + 'typeNonExistant';");
|
||||
// this will assign a non existant SCThingType to dishCopy
|
||||
dishCopy.type = typeNonExistant();
|
||||
const typeNonExistent = eval("(x) => x + 'typeNonExistent';");
|
||||
// this will assign a non-existent SCThingType to dishCopy
|
||||
dishCopy.type = typeNonExistent();
|
||||
const dishMetaTranslationsDE = translator.translatedPropertyNames(dishCopy.type);
|
||||
expect(dishMetaTranslationsDE).to.be.undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/*
|
||||
* Copyright (C) 2019 StApps
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
@@ -13,35 +14,35 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import {assert, Has, IsAny, IsNever, NotHas} from 'conditional-type-checks';
|
||||
import {SCThing, SCThingWithoutReferences} from '../src/things/abstract/thing.js';
|
||||
import {SCAcademicEvent, SCAcademicEventWithoutReferences} from '../src/things/academic-event.js';
|
||||
import {SCArticle, SCArticleWithoutReferences} from '../src/things/article.js';
|
||||
import {SCAssessment, SCAssessmentWithoutReferences} from '../src/things/assessment.js';
|
||||
import {SCBook, SCBookWithoutReferences} from '../src/things/book.js';
|
||||
import {SCBuilding, SCBuildingWithoutReferences} from '../src/things/building.js';
|
||||
import {SCCatalog, SCCatalogWithoutReferences} from '../src/things/catalog.js';
|
||||
import {SCContactPoint, SCContactPointWithoutReferences} from '../src/things/contact-point.js';
|
||||
import {SCCourseOfStudy, SCCourseOfStudyWithoutReferences} from '../src/things/course-of-study.js';
|
||||
import {SCDateSeries, SCDateSeriesWithoutReferences} from '../src/things/date-series.js';
|
||||
import {SCDiff, SCDiffWithoutReferences} from '../src/things/diff.js';
|
||||
import {SCDish, SCDishWithoutReferences} from '../src/things/dish.js';
|
||||
import {SCFavorite, SCFavoriteWithoutReferences} from '../src/things/favorite.js';
|
||||
import {SCFloor, SCFloorWithoutReferences} from '../src/things/floor.js';
|
||||
import {SCMessage, SCMessageWithoutReferences} from '../src/things/message.js';
|
||||
import {SCOrganization, SCOrganizationWithoutReferences} from '../src/things/organization.js';
|
||||
import {SCPerson, SCPersonWithoutReferences} from '../src/things/person.js';
|
||||
import {SCPointOfInterest, SCPointOfInterestWithoutReferences} from '../src/things/point-of-interest.js';
|
||||
import {SCRoom, SCRoomWithoutReferences} from '../src/things/room.js';
|
||||
import {SCSemester, SCSemesterWithoutReferences} from '../src/things/semester.js';
|
||||
import {SCSetting, SCSettingWithoutReferences} from '../src/things/setting.js';
|
||||
import {SCSportCourse, SCSportCourseWithoutReferences} from '../src/things/sport-course.js';
|
||||
import {SCStudyModule, SCStudyModuleWithoutReferences} from '../src/things/study-module.js';
|
||||
import {SCTicket, SCTicketWithoutReferences} from '../src/things/ticket.js';
|
||||
import {SCToDo, SCToDoWithoutReferences} from '../src/things/todo.js';
|
||||
import {SCTour, SCTourWithoutReferences} from '../src/things/tour.js';
|
||||
import {SCVideo, SCVideoWithoutReferences} from '../src/things/video.js';
|
||||
import {SCPeriodical, SCPeriodicalWithoutReferences} from '../src/things/periodical.js';
|
||||
import {SCPublicationEvent, SCPublicationEventWithoutReferences} from '../src/things/publication-event.js';
|
||||
import {SCThing, SCThingWithoutReferences} from '../src/index.js';
|
||||
import {SCAcademicEvent, SCAcademicEventWithoutReferences} from '../src/index.js';
|
||||
import {SCArticle, SCArticleWithoutReferences} from '../src/index.js';
|
||||
import {SCAssessment, SCAssessmentWithoutReferences} from '../src/index.js';
|
||||
import {SCBook, SCBookWithoutReferences} from '../src/index.js';
|
||||
import {SCBuilding, SCBuildingWithoutReferences} from '../src/index.js';
|
||||
import {SCCatalog, SCCatalogWithoutReferences} from '../src/index.js';
|
||||
import {SCContactPoint, SCContactPointWithoutReferences} from '../src/index.js';
|
||||
import {SCCourseOfStudy, SCCourseOfStudyWithoutReferences} from '../src/index.js';
|
||||
import {SCDateSeries, SCDateSeriesWithoutReferences} from '../src/index.js';
|
||||
import {SCDiff, SCDiffWithoutReferences} from '../src/index.js';
|
||||
import {SCDish, SCDishWithoutReferences} from '../src/index.js';
|
||||
import {SCFavorite, SCFavoriteWithoutReferences} from '../src/index.js';
|
||||
import {SCFloor, SCFloorWithoutReferences} from '../src/index.js';
|
||||
import {SCMessage, SCMessageWithoutReferences} from '../src/index.js';
|
||||
import {SCOrganization, SCOrganizationWithoutReferences} from '../src/index.js';
|
||||
import {SCPerson, SCPersonWithoutReferences} from '../src/index.js';
|
||||
import {SCPointOfInterest, SCPointOfInterestWithoutReferences} from '../src/index.js';
|
||||
import {SCRoom, SCRoomWithoutReferences} from '../src/index.js';
|
||||
import {SCSemester, SCSemesterWithoutReferences} from '../src/index.js';
|
||||
import {SCSetting, SCSettingWithoutReferences} from '../src/index.js';
|
||||
import {SCSportCourse, SCSportCourseWithoutReferences} from '../src/index.js';
|
||||
import {SCStudyModule, SCStudyModuleWithoutReferences} from '../src/index.js';
|
||||
import {SCTicket, SCTicketWithoutReferences} from '../src/index.js';
|
||||
import {SCToDo, SCToDoWithoutReferences} from '../src/index.js';
|
||||
import {SCTour, SCTourWithoutReferences} from '../src/index.js';
|
||||
import {SCVideo, SCVideoWithoutReferences} from '../src/index.js';
|
||||
import {SCPeriodical, SCPeriodicalWithoutReferences} from '../src/index.js';
|
||||
import {SCPublicationEvent, SCPublicationEventWithoutReferences} from '../src/index.js';
|
||||
|
||||
/**
|
||||
* Check if E extends T
|
||||
|
||||
Reference in New Issue
Block a user