add unit tests to app/utils/markdown (#8135)
This commit is contained in:
parent
0b83938d3c
commit
5261e29c38
2 changed files with 207 additions and 3 deletions
203
app/utils/markdown/index.test.ts
Normal file
203
app/utils/markdown/index.test.ts
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Platform, type TextStyle} from 'react-native';
|
||||
|
||||
import {Preferences} from '@constants';
|
||||
|
||||
import {
|
||||
getCodeFont,
|
||||
getMarkdownTextStyles,
|
||||
getMarkdownBlockStyles,
|
||||
getHighlightLanguageFromNameOrAlias,
|
||||
getHighlightLanguageName,
|
||||
escapeRegex,
|
||||
getMarkdownImageSize,
|
||||
computeTextStyle,
|
||||
parseSearchTerms,
|
||||
convertSearchTermToRegex,
|
||||
} from './index';
|
||||
|
||||
jest.mock('@utils/images', () => ({
|
||||
getViewPortWidth: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@utils/log', () => ({
|
||||
logError: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('Utility functions', () => {
|
||||
describe('getCodeFont', () => {
|
||||
it('should return the correct font for iOS', () => {
|
||||
Platform.OS = 'ios';
|
||||
expect(getCodeFont()).toBe('Menlo');
|
||||
});
|
||||
|
||||
it('should return the correct font for Android', () => {
|
||||
Platform.OS = 'android';
|
||||
expect(getCodeFont()).toBe('monospace');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMarkdownTextStyles', () => {
|
||||
it('should return correct text styles', () => {
|
||||
const styles = getMarkdownTextStyles(Preferences.THEMES.denim);
|
||||
expect(styles).toHaveProperty('emph');
|
||||
expect(styles).toHaveProperty('strong');
|
||||
expect(styles).toHaveProperty('del');
|
||||
expect(styles).toHaveProperty('link');
|
||||
expect(styles).toHaveProperty('heading1');
|
||||
expect(styles).toHaveProperty('code');
|
||||
expect(styles).toHaveProperty('mention');
|
||||
expect(styles).toHaveProperty('error');
|
||||
expect(styles).toHaveProperty('table_header_row');
|
||||
expect(styles).toHaveProperty('mention_highlight');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMarkdownBlockStyles', () => {
|
||||
it('should return correct block styles', () => {
|
||||
const styles = getMarkdownBlockStyles(Preferences.THEMES.denim);
|
||||
expect(styles).toHaveProperty('adjacentParagraph');
|
||||
expect(styles).toHaveProperty('horizontalRule');
|
||||
expect(styles).toHaveProperty('quoteBlockIcon');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHighlightLanguageFromNameOrAlias', () => {
|
||||
it('should return correct language name or alias', () => {
|
||||
expect(getHighlightLanguageFromNameOrAlias('javascript')).toBe('javascript');
|
||||
expect(getHighlightLanguageFromNameOrAlias('js')).toBe('javascript');
|
||||
expect(getHighlightLanguageFromNameOrAlias('unknown')).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHighlightLanguageName', () => {
|
||||
it('should return correct language name', () => {
|
||||
expect(getHighlightLanguageName('javascript')).toBe('JavaScript');
|
||||
expect(getHighlightLanguageName('unknown')).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('escapeRegex', () => {
|
||||
it('should escape special regex characters', () => {
|
||||
expect(escapeRegex('hello.*')).toBe('hello\\.\\*');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMarkdownImageSize', () => {
|
||||
it('should return correct size for sourceSize', () => {
|
||||
const size = getMarkdownImageSize(false, false, {width: 100, height: 200});
|
||||
expect(size).toEqual({width: 100, height: 200});
|
||||
});
|
||||
|
||||
it('should return correct size for sourceSize without height', () => {
|
||||
const size = getMarkdownImageSize(false, false, {width: 100});
|
||||
expect(size).toEqual({width: 100, height: 100});
|
||||
});
|
||||
|
||||
it('should return correct size for sourceSize without height and known size', () => {
|
||||
const size = getMarkdownImageSize(false, false, {width: 100}, {width: 100, height: 200});
|
||||
expect(size).toEqual({width: 100, height: 200});
|
||||
});
|
||||
|
||||
it('should return correct size for sourceSize height height and known size', () => {
|
||||
const size = getMarkdownImageSize(false, false, {height: 100}, {width: 100, height: 200});
|
||||
expect(size).toEqual({width: 50, height: 100});
|
||||
});
|
||||
|
||||
it('should return correct size for knownSize', () => {
|
||||
const size = getMarkdownImageSize(false, false, undefined, {width: 100, height: 200});
|
||||
expect(size).toEqual({width: 100, height: 200});
|
||||
});
|
||||
|
||||
it('should return correct size when no metadata and source size is not specified', () => {
|
||||
const size = getMarkdownImageSize(false, false, undefined, undefined, 150, 250);
|
||||
expect(size).toEqual({width: 150, height: 250});
|
||||
});
|
||||
});
|
||||
|
||||
describe('computeTextStyle', () => {
|
||||
const textStyles: { [key: string]: TextStyle } = {
|
||||
bold: {fontWeight: 'bold'},
|
||||
italic: {fontStyle: 'italic'},
|
||||
underline: {textDecorationLine: 'underline'},
|
||||
};
|
||||
|
||||
const baseStyle: TextStyle = {color: 'black'};
|
||||
|
||||
it('should return base style if context is empty', () => {
|
||||
expect(computeTextStyle(textStyles, baseStyle, [])).toEqual(baseStyle);
|
||||
});
|
||||
|
||||
it('should return base style if context has no matching styles', () => {
|
||||
expect(computeTextStyle(textStyles, baseStyle, ['unknown'])).toEqual(baseStyle);
|
||||
});
|
||||
|
||||
it('should apply a single context style', () => {
|
||||
expect(computeTextStyle(textStyles, baseStyle, ['bold'])).toEqual([baseStyle, textStyles.bold]);
|
||||
});
|
||||
|
||||
it('should apply multiple context styles', () => {
|
||||
expect(computeTextStyle(textStyles, baseStyle, ['bold', 'italic'])).toEqual([baseStyle, textStyles.bold, textStyles.italic]);
|
||||
});
|
||||
|
||||
it('should ignore undefined styles', () => {
|
||||
expect(computeTextStyle(textStyles, baseStyle, ['bold', 'unknown'])).toEqual([baseStyle, textStyles.bold]);
|
||||
});
|
||||
|
||||
it('should handle multiple undefined styles', () => {
|
||||
expect(computeTextStyle(textStyles, baseStyle, ['unknown1', 'unknown2'])).toEqual(baseStyle);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseSearchTerms', () => {
|
||||
it('should capture quoted strings', () => {
|
||||
expect(parseSearchTerms('"hello world"')).toEqual(['hello world']);
|
||||
});
|
||||
|
||||
it('should ignore search flags', () => {
|
||||
expect(parseSearchTerms('in:channel before:2021-01-01')).toEqual([]);
|
||||
});
|
||||
|
||||
it('should capture @ mentions', () => {
|
||||
expect(parseSearchTerms('@username')).toEqual(['username']);
|
||||
});
|
||||
|
||||
it('should capture plain text up to the next quote or search flag', () => {
|
||||
expect(parseSearchTerms('plain text "quoted text"')).toEqual(['plain', 'text', 'quoted text']);
|
||||
});
|
||||
|
||||
it('should split plain text into words', () => {
|
||||
expect(parseSearchTerms('this is a test')).toEqual(['this', 'is', 'a', 'test']);
|
||||
});
|
||||
|
||||
it('should handle a mix of all cases', () => {
|
||||
const searchTerm = 'in:channel @username "quoted text" plain text';
|
||||
const expected = ['username', 'quoted text', 'plain', 'text'];
|
||||
expect(parseSearchTerms(searchTerm)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('convertSearchTermToRegex', () => {
|
||||
it('should create regex for CJK characters', () => {
|
||||
const result = convertSearchTermToRegex('你好');
|
||||
expect(result.pattern).toEqual(/()(你好)/gi);
|
||||
});
|
||||
|
||||
it('should create regex for wildcard at the end', () => {
|
||||
const result = convertSearchTermToRegex('hello*');
|
||||
expect(result.pattern).toEqual(/\b()(hello)/gi);
|
||||
});
|
||||
|
||||
it('should create regex for mentions and hashtags', () => {
|
||||
const result = convertSearchTermToRegex('@user');
|
||||
expect(result.pattern).toEqual(/(\W|^)(@user)\b/gi);
|
||||
});
|
||||
|
||||
it('should create regex for plain text', () => {
|
||||
const result = convertSearchTermToRegex('hello');
|
||||
expect(result.pattern).toEqual(/\b()(hello)\b/gi);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -331,10 +331,11 @@ export function parseSearchTerms(searchTerm: string): string[] | undefined {
|
|||
}
|
||||
|
||||
// remove punctuation from each term
|
||||
terms = terms.map((term) => {
|
||||
term.replace(puncStart, '');
|
||||
terms = terms.map((t) => {
|
||||
let term = t;
|
||||
term = term.replace(puncStart, '');
|
||||
if (term.charAt(term.length - 1) !== '*') {
|
||||
term.replace(puncEnd, '');
|
||||
term = term.replace(puncEnd, '');
|
||||
}
|
||||
return term;
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue