Add tests without Intl.Segmenter

This commit is contained in:
Sidharth Vinod 2023-07-07 10:02:04 +05:30
parent b14bcda12a
commit d58c41dbc0
No known key found for this signature in database
GPG Key ID: FB5CCD378D3907CD
3 changed files with 103 additions and 58 deletions

View File

@ -14,11 +14,7 @@ function applyStyle(dom, styleFn) {
function addHtmlSpan(element, node, width, classes, addBackground = false) {
const fo = element.append('foreignObject');
// const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
// const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
const div = fo.append('xhtml:div');
// const div = body.append('div');
// const div = fo.append('div');
const label = node.label;
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
@ -130,7 +126,6 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) {
.attr('font-style', word.type === 'emphasis' ? 'italic' : 'normal')
.attr('class', 'text-inner-tspan')
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal');
// const special = ['"', "'", '.', ',', ':', ';', '!', '?', '(', ')', '[', ']', '{', '}'];
if (index === 0) {
innerTspan.text(word.content);
} else {

View File

@ -1,46 +1,85 @@
import { splitTextToChars, splitLineToFitWidth, splitLineToWords } from './splitText.js';
import { describe, it, expect } from 'vitest';
import { describe, it, expect, vi } from 'vitest';
import type { CheckFitFunction, MarkdownLine, MarkdownWordType } from './types.js';
describe('splitText', () => {
it.each([
{ str: '', split: [] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: 'ok', split: ['o', 'k'] },
{ str: 'abc', split: ['a', 'b', 'c'] },
])('should split $str into graphemes', ({ str, split }: { str: string; split: string[] }) => {
expect(splitTextToChars(str)).toEqual(split);
describe('when Intl.Segmenter is available', () => {
describe('splitText', () => {
it.each([
{ str: '', split: [] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: 'ok', split: ['o', 'k'] },
{ str: 'abc', split: ['a', 'b', 'c'] },
])('should split $str into graphemes', ({ str, split }: { str: string; split: string[] }) => {
expect(splitTextToChars(str)).toEqual(split);
});
});
describe('split lines', () => {
it('should create valid checkFit function', () => {
const checkFit5 = createCheckFn(5);
expect(checkFit5([{ content: 'hello', type: 'normal' }])).toBe(true);
expect(
checkFit5([
{ content: 'hello', type: 'normal' },
{ content: 'world', type: 'normal' },
])
).toBe(false);
const checkFit1 = createCheckFn(1);
expect(checkFit1([{ content: 'A', type: 'normal' }])).toBe(true);
expect(checkFit1([{ content: '🏳️‍⚧️', type: 'normal' }])).toBe(true);
expect(checkFit1([{ content: '🏳️‍⚧️🏳️‍⚧️', type: 'normal' }])).toBe(false);
});
it.each([
// empty string
{ str: 'hello world', width: 7, split: ['hello', 'world'] },
// width > full line
{ str: 'hello world', width: 20, split: ['hello world'] },
// width < individual word
{ str: 'hello world', width: 3, split: ['hel', 'lo', 'wor', 'ld'] },
{ str: 'hello 12 world', width: 4, split: ['hell', 'o 12', 'worl', 'd'] },
{ str: 'hello 1 2 world', width: 4, split: ['hell', 'o 1', '2', 'worl', 'd'] },
{ str: 'hello 1 2 world', width: 6, split: ['hello', ' 1 2', 'world'] },
// width = 0, impossible, so split into individual characters
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 0, split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 1, split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 2, split: ['🏳️‍⚧️🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 3, split: ['🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'] },
{ str: '中文中', width: 1, split: ['中', '文', '中'] },
{ str: '中文中', width: 2, split: ['中文', '中'] },
{ str: '中文中', width: 3, split: ['中文中'] },
{ str: 'Flag 🏳️‍⚧️ this 🏳️‍🌈', width: 6, split: ['Flag 🏳️‍⚧️', 'this 🏳️‍🌈'] },
])(
'should split $str into lines of $width characters',
({ str, split, width }: { str: string; width: number; split: string[] }) => {
const checkFn = createCheckFn(width);
const line: MarkdownLine = getLineFromString(str);
expect(splitLineToFitWidth(line, checkFn)).toEqual(
split.map((str) => getLineFromString(str))
);
}
);
});
});
describe('split lines', () => {
/**
* Creates a checkFunction for a given width
* @param width - width of characters to fit in a line
* @returns checkFunction
*/
const createCheckFn = (width: number): CheckFitFunction => {
return (text: MarkdownLine) => {
// Join all words into a single string
const joinedContent = text.map((w) => w.content).join('');
const characters = splitTextToChars(joinedContent);
return characters.length <= width;
};
};
describe('when Intl.segmenter is not available', () => {
beforeAll(() => {
vi.stubGlobal('Intl', { Segmenter: undefined });
});
afterAll(() => {
vi.unstubAllGlobals();
});
it('should create valid checkFit function', () => {
const checkFit5 = createCheckFn(5);
expect(checkFit5([{ content: 'hello', type: 'normal' }])).toBe(true);
expect(
checkFit5([
{ content: 'hello', type: 'normal' },
{ content: 'world', type: 'normal' },
])
).toBe(false);
const checkFit1 = createCheckFn(1);
expect(checkFit1([{ content: 'A', type: 'normal' }])).toBe(true);
expect(checkFit1([{ content: '🏳️‍⚧️', type: 'normal' }])).toBe(true);
expect(checkFit1([{ content: '🏳️‍⚧️🏳️‍⚧️', type: 'normal' }])).toBe(false);
it.each([
{ str: '', split: [] },
{
str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻',
split: [...'🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'],
},
{ str: 'ok', split: ['o', 'k'] },
{ str: 'abc', split: ['a', 'b', 'c'] },
])('should split $str into characters', ({ str, split }: { str: string; split: string[] }) => {
expect(splitTextToChars(str)).toEqual(split);
});
it.each([
@ -52,37 +91,34 @@ describe('split lines', () => {
{ str: 'hello world', width: 3, split: ['hel', 'lo', 'wor', 'ld'] },
{ str: 'hello 12 world', width: 4, split: ['hell', 'o 12', 'worl', 'd'] },
{ str: 'hello 1 2 world', width: 4, split: ['hell', 'o 1', '2', 'worl', 'd'] },
{ str: 'hello 1 2 world', width: 6, split: ['hello', ' 1 2', 'world'] },
{ str: 'hello 1 2 world', width: 6, split: ['hello', ' 1 2', 'world'] },
// width = 0, impossible, so split into individual characters
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 0, split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 1, split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 2, split: ['🏳️‍⚧️🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 3, split: ['🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'] },
{ str: 'abc', width: 0, split: ['a', 'b', 'c'] },
{ str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 1, split: [...'🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'] },
{ str: '中文中', width: 1, split: ['中', '文', '中'] },
{ str: '中文中', width: 2, split: ['中文', '中'] },
{ str: '中文中', width: 3, split: ['中文中'] },
{ str: 'Flag 🏳️‍⚧️ this 🏳️‍🌈', width: 6, split: ['Flag 🏳️‍⚧️', 'this 🏳️‍🌈'] },
])(
'should split $str into lines of $width characters',
({ str, split, width }: { str: string; width: number; split: string[] }) => {
const checkFn = createCheckFn(width);
const line: MarkdownLine = getLineFromString(str);
expect(splitLineToFitWidth(line, checkFn)).toEqual(
split.map((str) => splitLineToWords(str).map((content) => ({ content, type: 'normal' })))
split.map((str) => getLineFromString(str))
);
}
);
});
it('should handle strings with newlines', () => {
const checkFn: CheckFitFunction = createCheckFn(6);
const str = `Flag
it('should handle strings with newlines', () => {
const checkFn: CheckFitFunction = createCheckFn(6);
const str = `Flag
🏳 this 🏳🌈`;
expect(() =>
splitLineToFitWidth(getLineFromString(str), checkFn)
).toThrowErrorMatchingInlineSnapshot(
'"splitLineToFitWidth does not support newlines in the line"'
);
});
expect(() =>
splitLineToFitWidth(getLineFromString(str), checkFn)
).toThrowErrorMatchingInlineSnapshot(
'"splitLineToFitWidth does not support newlines in the line"'
);
});
const getLineFromString = (str: string, type: MarkdownWordType = 'normal'): MarkdownLine => {
@ -91,3 +127,17 @@ const getLineFromString = (str: string, type: MarkdownWordType = 'normal'): Mark
type,
}));
};
/**
* Creates a checkFunction for a given width
* @param width - width of characters to fit in a line
* @returns checkFunction
*/
const createCheckFn = (width: number): CheckFitFunction => {
return (text: MarkdownLine) => {
// Join all words into a single string
const joinedContent = text.map((w) => w.content).join('');
const characters = splitTextToChars(joinedContent);
return characters.length <= width;
};
};

View File

@ -22,7 +22,7 @@ export function splitLineToWords(text: string): string[] {
// Split by ' ' removes the ' 's from the result.
const words = text.split(' ');
// Add the ' 's back to the result.
const wordsWithSpaces = words.flatMap((s) => [s, ' ']);
const wordsWithSpaces = words.flatMap((s) => [s, ' ']).filter((s) => s);
// Remove last space.
wordsWithSpaces.pop();
return wordsWithSpaces;