fix(post): link board-specific option errors to supported boards

When fortune or dice options are used on the wrong board, show which
boards support them with clickable links in the post form and reply modal.
This commit is contained in:
Tommaso Casaburi
2026-05-24 19:17:50 +07:00
parent 0df81b598e
commit 5fad3c73ba
9 changed files with 220 additions and 50 deletions
@@ -1,18 +1,40 @@
import { describe, expect, it } from 'vitest';
import { getNonokoPendingAccountCommentIndex, getNonokoPendingRouteState, getUnsupportedPostOptionsMessage, hasNonokoOption } from '../post-options-utils';
import {
getNonokoPendingAccountCommentIndex,
getNonokoPendingRouteState,
getPostOptionsValidationError,
getUnsupportedPostOptionsMessage,
hasNonokoOption,
} from '../post-options-utils';
describe('post-options-utils', () => {
it('rejects additional dice options instead of dropping them', () => {
expect(getUnsupportedPostOptionsMessage('dice+1d6 dice+1d20', 'qst')).toBe('unsupported options: dice+1d20');
expect(getUnsupportedPostOptionsMessage('dice+1d6 dice+1d20', 'qst')).toBe('Unsupported options: dice+1d20.');
});
it('supports nonoko while keeping sage unsupported', () => {
expect(getUnsupportedPostOptionsMessage('nonoko', undefined)).toBeNull();
expect(getUnsupportedPostOptionsMessage('sage', 'b')).toBe('unsupported options: sage');
expect(getUnsupportedPostOptionsMessage('sage', 'b')).toBe('Unsupported options: sage.');
expect(hasNonokoOption('fortune nonoko')).toBe(true);
expect(hasNonokoOption('nonokosage')).toBe(false);
});
it('describes board-specific options with supported directories', () => {
expect(getPostOptionsValidationError('fortune', 'mu')).toEqual({
unsupportedOptions: ['fortune'],
supportedDirectoryCodesByOption: [{ option: 'fortune', directoryCodes: ['b', 's5s'] }],
});
expect(getUnsupportedPostOptionsMessage('fortune', 'mu')).toBe('Unsupported options: fortune. Option "fortune" is supported on: /b/, /s5s/.');
expect(getUnsupportedPostOptionsMessage('sage fortune', 'pol')).toBe('Unsupported options: sage, fortune. Option "fortune" is supported on: /b/, /s5s/.');
expect(getPostOptionsValidationError('fortune dice+1d6', 'mu')).toEqual({
unsupportedOptions: ['fortune', 'dice+1d6'],
supportedDirectoryCodesByOption: [
{ option: 'fortune', directoryCodes: ['b', 's5s'] },
{ option: 'dice+1d6', directoryCodes: ['qst', 'tg'] },
],
});
});
it('reads the nonoko pending account comment index from direct and wrapped route state', () => {
expect(getNonokoPendingRouteState(7)).toEqual({ nonokoPendingAccountCommentIndex: 7 });
expect(getNonokoPendingAccountCommentIndex({ nonokoPendingAccountCommentIndex: 7 })).toBe(7);