mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-03 11:07:00 -04:00
212 lines
8.6 KiB
TypeScript
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');
|
|
});
|
|
});
|