/* * Copyright (C) 2019 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import {expect} from 'chai'; import clone from 'rfdc'; 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'); // this will simulate a translator always utilizing the base language translations const translatorWithFallback = new SCThingTranslator('tt'); const translatedThingDE = translator.translate(dish); const translatedThingFallback = translatorWithFallback.translate(dish); describe('Translator', function () { this.timeout(10_000); this.slow(5000); describe('direct', function () { it('should translate enum single value', function () { expect(translator.translatedAccess(setting).inputType).to.equal('einfache Auswahl'); }); it('should translate string literal type', function () { expect(translator.translatedAccess(dish).type).to.equal('Essen'); expect(translatedThingDE.type).to.equal('Essen'); }); it('should translate string property', function () { expect(translator.translatedAccess(dish).name).to.equal('de-dish-name'); expect(translatedThingDE.name).to.equal('de-dish-name'); }); 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'}, ]); }); 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'}); }); 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']); }); 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'); }); }); 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'); }); 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'); }); 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']); }); 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'); }); }); 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 destructivelyTranslatedDish = translatorDE.translate(dish); (dishCopy.origin as SCThingRemoteOrigin).name = 'translator.spec'; expect(translatorDE.translatedAccess(dishCopy)).not.to.deep.equal(translatedDish); expect(translatorDE.translate(dishCopy)).not.to.equal(destructivelyTranslatedDish); }); 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.translate(dish).name).to.equal('de-dish-name'); translatorDE.language = 'en'; expect(translatorDE.translatedAccess(dish).name).to.equal('base-dish-name'); expect(translatorDE.translate(dish).name).to.equal('base-dish-name'); }); 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'); } }); }); 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); }); 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); }); 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]); }); it('should translate thing without meta class', function () { const dishCopy = clone()(dish); 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; }); });