mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
159 lines
5.8 KiB
TypeScript
159 lines
5.8 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import en from '@/locales/en/common.json';
|
|
import {
|
|
type SettingsSearchTab,
|
|
type SubResult,
|
|
collectSubResults,
|
|
flattenStrings,
|
|
getByPath,
|
|
tabSearchPaths,
|
|
withAppName,
|
|
} from '../settings-search';
|
|
|
|
function subResultsFor(tab: SettingsSearchTab): SubResult[] {
|
|
const list: SubResult[] = [];
|
|
for (const path of tabSearchPaths[tab]) {
|
|
collectSubResults(getByPath(en, path), list);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
function haystackFor(tab: SettingsSearchTab): string {
|
|
const strings: string[] = [];
|
|
for (const path of tabSearchPaths[tab]) {
|
|
flattenStrings(getByPath(en, path), strings);
|
|
}
|
|
return strings.join(' ').toLowerCase();
|
|
}
|
|
|
|
function labelsFor(tab: SettingsSearchTab): string[] {
|
|
return subResultsFor(tab).map((r) => r.label);
|
|
}
|
|
|
|
describe('collectSubResults', () => {
|
|
it('emits flat `key` / `key_desc` string pairs as a labelled sub-result', () => {
|
|
const list: SubResult[] = [];
|
|
collectSubResults(
|
|
{
|
|
title: 'Calendar settings',
|
|
free_scroll: 'Free scrolling',
|
|
free_scroll_desc: 'Scroll continuously',
|
|
hover_preview_off: 'Disabled',
|
|
},
|
|
list
|
|
);
|
|
expect(list).toEqual([
|
|
{ label: 'Calendar settings', description: undefined },
|
|
{ label: 'Free scrolling', description: 'Scroll continuously' },
|
|
]);
|
|
});
|
|
|
|
it('still emits label/description objects and *_label keys', () => {
|
|
const list: SubResult[] = [];
|
|
collectSubResults(
|
|
{
|
|
name_label: 'Name',
|
|
nested: { label: 'Theme', description: 'Pick one', dark: 'Dark' },
|
|
},
|
|
list
|
|
);
|
|
expect(list).toEqual([
|
|
{ label: 'Name' },
|
|
{ label: 'Theme', description: 'Pick one' },
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('settings search index (English messages)', () => {
|
|
it('every tab path resolves to a translation subtree', () => {
|
|
const missing: string[] = [];
|
|
for (const paths of Object.values(tabSearchPaths)) {
|
|
for (const path of paths) {
|
|
if (getByPath(en, path) === undefined) missing.push(path);
|
|
}
|
|
}
|
|
expect(missing).toEqual([]);
|
|
});
|
|
|
|
it('lists the calendar toggles as sub-results', () => {
|
|
const labels = labelsFor('calendar');
|
|
expect(labels).toContain('Free scrolling');
|
|
expect(labels).toContain('Show week numbers');
|
|
expect(labels).toContain('Organize invitations as');
|
|
expect(labels).toContain('Parse email invitations');
|
|
expect(labelsFor('notifications')).toContain('Unread Count on Tab and App Icon');
|
|
expect(labelsFor('notifications')).not.toContain('Parse email invitations');
|
|
expect(labels).toContain('Contact birthday calendar');
|
|
// Option values are not settings of their own.
|
|
expect(labels).not.toContain('Disabled');
|
|
});
|
|
|
|
it('finds the newer mail settings on their tabs', () => {
|
|
expect(labelsFor('message_list')).toContain('Clear search when switching folders');
|
|
expect(labelsFor('message_list')).toContain('Swipe right action (mobile)');
|
|
expect(labelsFor('message_list')).toContain('Message list order');
|
|
expect(labelsFor('reading')).toContain('Trusted Senders');
|
|
expect(labelsFor('reading')).toContain('Email (.eml) filename');
|
|
expect(labelsFor('reading')).not.toContain('Delete Action');
|
|
expect(labelsFor('composing')).toContain('Undo send / send delay');
|
|
expect(labelsFor('composing')).toContain('Request read receipts by default');
|
|
expect(labelsFor('composing')).toContain('Email Templates');
|
|
expect(labelsFor('composing')).toContain('Quick Reply');
|
|
expect(labelsFor('composing')).toContain('Placeholder warning');
|
|
expect(labelsFor('composing')).not.toContain('Sub-Address Delimiter');
|
|
expect(labelsFor('appearance')).toContain('Pro Interface (Experimental)');
|
|
expect(labelsFor('account')).toContain('Tell accounts apart');
|
|
expect(labelsFor('account')).toContain('Your Identities');
|
|
expect(labelsFor('appearance')).toContain('Themes');
|
|
expect(labelsFor('general')).toContain('Time zone');
|
|
expect(labelsFor('general')).toContain('Email links');
|
|
expect(labelsFor('organize')).toContain('Nested Tags');
|
|
expect(haystackFor('organize')).toContain('standard folder roles');
|
|
});
|
|
|
|
it('matches the calendar tab for a free-scroll query', () => {
|
|
expect(haystackFor('calendar')).toContain('free scrolling');
|
|
expect(haystackFor('general')).toContain('time zone');
|
|
});
|
|
});
|
|
|
|
describe('{appName} in the index (#1314)', () => {
|
|
const index = (appName: string) => {
|
|
const list: SubResult[] = [];
|
|
const strings: string[] = [];
|
|
for (const path of tabSearchPaths.general) {
|
|
const node = withAppName(getByPath(en, path), appName);
|
|
collectSubResults(node, list);
|
|
flattenStrings(node, strings);
|
|
}
|
|
return { list, haystack: strings.join(' ').toLowerCase() };
|
|
};
|
|
|
|
it('never keeps the raw placeholder', () => {
|
|
for (const tab of Object.keys(tabSearchPaths) as SettingsSearchTab[]) {
|
|
for (const path of tabSearchPaths[tab]) {
|
|
expect(JSON.stringify(withAppName(getByPath(en, path), 'Bulwark')) ?? '').not.toContain('{appName}');
|
|
}
|
|
}
|
|
});
|
|
|
|
it('finds Default apps by "bulwark" on a stock install', () => {
|
|
const { list, haystack } = index('Bulwark');
|
|
expect(haystack).toContain('bulwark');
|
|
expect(list.some((r) => r.description?.includes('Bulwark'))).toBe(true);
|
|
});
|
|
|
|
it('finds Default apps by the configured name', () => {
|
|
const { list, haystack } = index('Rath Mail');
|
|
expect(haystack).toContain('rath mail');
|
|
const links: string[] = [];
|
|
flattenStrings(withAppName(getByPath(en, 'protocol_handlers'), 'Rath Mail'), links);
|
|
expect(links.join(' ').toLowerCase()).not.toContain('bulwark');
|
|
expect(list.some((r) => r.description?.includes('Rath Mail'))).toBe(true);
|
|
});
|
|
|
|
it('leaves other values alone', () => {
|
|
expect(withAppName({ a: 'x {appName} y', b: ['{appName}'], c: 3 }, 'N')).toEqual({ a: 'x N y', b: ['N'], c: 3 });
|
|
});
|
|
});
|