mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'codex/fix/option-board-support-alert'
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -19,6 +19,20 @@ export interface DiceRoll {
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface PostOptionsValidationError {
|
||||
unsupportedOptions: string[];
|
||||
supportedDirectoryCodesByOption: Array<{ option: string; directoryCodes: string[] }>;
|
||||
}
|
||||
|
||||
export const isPostOptionsValidationError = (error: unknown): error is PostOptionsValidationError => {
|
||||
if (!error || typeof error !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const value = error as Partial<PostOptionsValidationError>;
|
||||
return Array.isArray(value.unsupportedOptions) && Array.isArray(value.supportedDirectoryCodesByOption);
|
||||
};
|
||||
|
||||
interface PostOptionsDirectory {
|
||||
directoryCode?: string;
|
||||
title?: string;
|
||||
@@ -88,27 +102,62 @@ const isSupportedPostOption = (option: string, directoryCode: string | undefined
|
||||
return !!parseDiceOption(option) && !!directoryCode && DICE_DIRECTORY_CODES.has(directoryCode);
|
||||
};
|
||||
|
||||
const getUnsupportedPostOptions = (value: string, directoryCode: string | undefined): string[] => {
|
||||
let hasDiceOption = false;
|
||||
const getSupportedDirectoryCodes = (option: string): string[] => {
|
||||
if (option === 'fortune') {
|
||||
return [...FORTUNE_DIRECTORY_CODES];
|
||||
}
|
||||
|
||||
return parsePostOptions(value).filter((option) => {
|
||||
return parseDiceOption(option) ? [...DICE_DIRECTORY_CODES] : [];
|
||||
};
|
||||
|
||||
export const getPostOptionsValidationError = (value: string, directoryCode: string | undefined): PostOptionsValidationError | null => {
|
||||
let hasDiceOption = false;
|
||||
const unsupportedOptions: string[] = [];
|
||||
const supportedDirectoryCodesByOption: Array<{ option: string; directoryCodes: string[] }> = [];
|
||||
|
||||
for (const option of parsePostOptions(value)) {
|
||||
const diceOption = parseDiceOption(option);
|
||||
if (diceOption && directoryCode && DICE_DIRECTORY_CODES.has(directoryCode)) {
|
||||
const isExtraDiceOption = hasDiceOption;
|
||||
hasDiceOption = true;
|
||||
return isExtraDiceOption;
|
||||
if (isExtraDiceOption) {
|
||||
unsupportedOptions.push(option);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
return !isSupportedPostOption(option, directoryCode);
|
||||
});
|
||||
if (isSupportedPostOption(option, directoryCode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const optionDirectoryCodes = getSupportedDirectoryCodes(option);
|
||||
if (optionDirectoryCodes.length > 0) {
|
||||
unsupportedOptions.push(option);
|
||||
if (!supportedDirectoryCodesByOption.some((entry) => entry.option === option)) {
|
||||
supportedDirectoryCodesByOption.push({ option, directoryCodes: optionDirectoryCodes });
|
||||
}
|
||||
} else {
|
||||
unsupportedOptions.push(option);
|
||||
}
|
||||
}
|
||||
|
||||
return unsupportedOptions.length > 0 ? { unsupportedOptions, supportedDirectoryCodesByOption } : null;
|
||||
};
|
||||
|
||||
export const getUnsupportedPostOptionsMessage = (value: string, directoryCode: string | undefined): string | null => {
|
||||
const unsupportedOptions = getUnsupportedPostOptions(value, directoryCode);
|
||||
return unsupportedOptions.length > 0 ? `unsupported options: ${unsupportedOptions.join(', ')}` : null;
|
||||
};
|
||||
const error = getPostOptionsValidationError(value, directoryCode);
|
||||
if (!error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export const isUnsupportedPostOptionsMessage = (message: string | null): boolean => message?.startsWith('unsupported options:') === true;
|
||||
let message = `Unsupported options: ${error.unsupportedOptions.join(', ')}.`;
|
||||
|
||||
for (const { option, directoryCodes } of error.supportedDirectoryCodesByOption) {
|
||||
message += ` Option "${option}" is supported on: ${directoryCodes.map((code) => `/${code}/`).join(', ')}.`;
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
||||
export const hasNonokoOption = (value: string): boolean => parsePostOptions(value).includes('nonoko');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user