PronounsPage/test/classes.test.ts

212 lines
8.6 KiB
TypeScript

import { beforeEach, describe, expect, test } from 'vitest';
import type { Translations } from '~/locale/translations.ts';
import { MergedPronounGroup, PronounGroup, PronounLibrary } from '~/src/classes.ts';
import { Example } from '~/src/language/examples.ts';
import { Translator } from '~/src/translator.ts';
import { configWithPronouns } from '~/test/fixtures/config.ts';
import pronounsFactory, { generated as generatedPronouns } from '~/test/fixtures/pronouns.ts';
const translations: Translations = {
pronouns: {
any: {
short: 'any',
},
slashes: {
plural: 'plural',
pluralHonorific: 'plural-honorific',
description: 'description',
},
},
};
const translator = new Translator(translations, translations, configWithPronouns);
let config = structuredClone(configWithPronouns);
const pronouns = Object.fromEntries(Object.entries(pronounsFactory)
.map(([name, pronounFactory]) => [name, pronounFactory(config)]));
beforeEach(() => {
config = structuredClone(configWithPronouns);
});
const inlineMorphemeExample = new Example([
'This house is ',
{ type: 'morpheme', morpheme: 'possessive_pronoun' },
]);
const capitalizedMorphemeExample = new Example([
{ type: 'morpheme', morpheme: 'pronoun_subject', capitalise: true },
' is very nice.',
]);
describe('morphemes of examples', () => {
test('are contained when present as variable', () => {
expect(inlineMorphemeExample.hasMorpheme('possessive_pronoun')).toBe(true);
});
test('are contained when present as capitalized variable', () => {
expect(capitalizedMorphemeExample.hasMorpheme('pronoun_subject')).toBe(true);
});
test('are not contained when missing as variable', () => {
expect(inlineMorphemeExample.hasMorpheme('pronoun_subject')).toBe(false);
});
});
describe('required morphemes for an example', () => {
test('are present if all morphemes are present', () => {
expect(inlineMorphemeExample.areRequiredExampleValuesPresent(pronouns.they.toExampleValues()))
.toBe(true);
});
test('are present even if one morpheme is empty', () => {
const pronoun = generatedPronouns.aerWithEmptyPossessivePronoun(config);
expect(inlineMorphemeExample.areRequiredExampleValuesPresent(pronoun.toExampleValues()))
.toBe(true);
});
test('are missing if one morpheme is null', () => {
const pronoun = generatedPronouns.aerWithUnsetPossessivePronoun(config);
expect(inlineMorphemeExample.areRequiredExampleValuesPresent(pronoun.toExampleValues()))
.toBe(false);
});
});
describe('formatting a pronoun with slashes', () => {
describe('when slashes are not configured', () => {
test('yields no result', () => {
expect(generatedPronouns.aer(config).toStringSlashes(translator)).toBeNull();
});
});
describe('when configured that slashes contain all morphemes', () => {
beforeEach(() => {
config.pronouns.generator!.slashes = true;
});
test('chunks contain all morphemes', () => {
expect(generatedPronouns.aer(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/aers/aerself');
});
test('morphemes with control symbols gets escaped', () => {
expect(generatedPronouns.sSlashHe(config).toStringSlashes(translator))
.toEqual('s`/he/hir/hir/hirs/hirself');
});
test('empty morphemes receive space as placeholder', () => {
expect(generatedPronouns.aerWithEmptyPossessivePronoun(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/ /aerself');
});
test('empty morphemes at end receive url-encoded space as placeholder', () => {
expect(generatedPronouns.aerWithEmptyReflexive(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/aers/%20');
});
test('unset morphemes receive tilde as placeholder', () => {
expect(generatedPronouns.aerWithUnsetPossessivePronoun(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/~/aerself');
});
test('adds plural modifier if necessary', () => {
expect(generatedPronouns.aerPlural(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/aers/aerselves/:plural');
});
test('adds plural honorific modifier if necessary', () => {
expect(generatedPronouns.aerPluralHonorific(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/aers/aerselves/:plural-honorific');
});
test('adds escaped description if necessary', () => {
expect(generatedPronouns.aerWithDescription(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/aers/aerself/:description=Neopronoun “ae” `/ “æ”');
});
test('adds multiple modifiers if necessary', () => {
expect(generatedPronouns.aerPluralWithDescription(config).toStringSlashes(translator))
.toEqual('ae/aer/aer/aers/aerselves/:plural/:description=Neopronoun “ae” `/ “æ”');
});
});
describe('when configured that slashes contain some morphemes', () => {
beforeEach(() => {
config.pronouns.generator!.slashes =
['pronoun_subject', 'pronoun_object', 'possessive_determiner', 'reflexive'];
});
test('chunks contain configured morphemes', () => {
expect(generatedPronouns.aer(config).toStringSlashes(translator)).toEqual('ae/aer/aer/aerself');
});
});
});
describe('when merging pronoun groups by key', () => {
test('groups without keys are not assigned a merged group', () => {
const groups = [
new PronounGroup('Normative-ish forms', ['they']),
];
const library = new PronounLibrary(config, groups, pronouns);
expect(library.byKey()).toEqual({});
});
test('groups with different keys are assigned different merged groups', () => {
const groups = [
new PronounGroup('Binary forms', ['he', 'she'], null, 'normative'),
new PronounGroup('Normative-ish forms', ['they'], null, 'normative-ish'),
];
const library = new PronounLibrary(config, groups, pronouns);
expect(library.byKey()).toEqual({
'normative': new MergedPronounGroup('normative', [
{
group: groups[0],
groupPronouns: { he: pronouns.he, she: pronouns.she },
},
]),
'normative-ish': new MergedPronounGroup('normative-ish', [
{
group: groups[1],
groupPronouns: { they: pronouns.they },
},
]),
});
});
test('groups with same key are assigned same merged group', () => {
const groups = [
new PronounGroup('Binary forms', ['he', 'she'], null, 'normative-ish'),
new PronounGroup('Normative-ish forms', ['they'], null, 'normative-ish'),
];
const library = new PronounLibrary(config, groups, pronouns);
expect(library.byKey()).toEqual({
'normative-ish': new MergedPronounGroup('normative-ish', [
{
group: groups[0],
groupPronouns: { he: pronouns.he, she: pronouns.she },
},
{
group: groups[1],
groupPronouns: { they: pronouns.they },
},
]),
});
});
});
describe('when displaying merged groups', () => {
test('and no group specific translation is available, the key is used', () => {
const group = new PronounGroup('Binary forms', ['he', 'she'], null, 'normative-ish');
const merged = new MergedPronounGroup('normative', [
{
group,
groupPronouns: { he: pronouns.he, she: pronouns.she },
},
]);
expect(merged.short(translator)).toBe('any normative');
});
test('and a group specific translation is available, the translation is used', () => {
translations.pronouns.any.group = {
normative: {
short: 'both binaries',
},
};
const group = new PronounGroup('Binary forms', ['he', 'she'], null, 'normative-ish');
const merged = new MergedPronounGroup('normative', [
{
group,
groupPronouns: { he: pronouns.he, she: pronouns.she },
},
]);
expect(merged.short(translator)).toBe('both binaries');
});
});