update
This commit is contained in:
125
tests/unit/stats.test.js
Normal file
125
tests/unit/stats.test.js
Normal file
@@ -0,0 +1,125 @@
|
||||
// Stage 7 tests: stats.js
|
||||
//
|
||||
// 覆盖:
|
||||
// - countWords:CJK 单字 + 拉丁词 + 混合 + 边界
|
||||
// - getTextStats:chars / words / lines 三个字段 + 空文档边界
|
||||
// - formatStatusStats:中文 locale + 0/1/N 行
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { countWords, getTextStats, formatStatusStats } from '../../src/stats.js';
|
||||
|
||||
describe('countWords', () => {
|
||||
it('空字符串 → 0', () => {
|
||||
expect(countWords('')).toBe(0);
|
||||
});
|
||||
|
||||
it('纯空白 → 0', () => {
|
||||
expect(countWords(' \n \t')).toBe(0);
|
||||
});
|
||||
|
||||
it('null / undefined → 0', () => {
|
||||
expect(countWords(null)).toBe(0);
|
||||
expect(countWords(undefined)).toBe(0);
|
||||
});
|
||||
|
||||
it('非字符串 → 0', () => {
|
||||
expect(countWords(42)).toBe(0);
|
||||
expect(countWords({})).toBe(0);
|
||||
});
|
||||
|
||||
it('纯拉丁词按空格分', () => {
|
||||
expect(countWords('hello world foo bar')).toBe(4);
|
||||
});
|
||||
|
||||
it('中文每个字算 1', () => {
|
||||
expect(countWords('你好世界')).toBe(4);
|
||||
});
|
||||
|
||||
it('中日韩混合', () => {
|
||||
expect(countWords('Hello 你好 World 世界')).toBe(6); // 4 CJK + 2 latin
|
||||
});
|
||||
|
||||
it('日文假名 + 韩文', () => {
|
||||
expect(countWords('こんにちは 안녕하세요')).toBe(10); // 5 hiragana + 5 hangul
|
||||
});
|
||||
|
||||
it('标点不计数', () => {
|
||||
expect(countWords('!!! ??? ...')).toBe(0);
|
||||
});
|
||||
|
||||
it('「hello-world」是一个词', () => {
|
||||
expect(countWords('hello-world')).toBe(1);
|
||||
});
|
||||
|
||||
it('多行', () => {
|
||||
expect(countWords('first line\nsecond line\nthird line')).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTextStats', () => {
|
||||
it('空字符串 → chars 0, words 0, lines 0', () => {
|
||||
// audit L8:空内容不再用 `|| 1` 兜底为 1 行。状态栏会显示「0 词」,
|
||||
// 避免「刚打开一个空白文件就看到『1 行』误导」。
|
||||
expect(getTextStats('')).toEqual({ chars: 0, words: 0, lines: 0 });
|
||||
});
|
||||
|
||||
it('纯空白 → lines 0', () => {
|
||||
const stats = getTextStats(' \n \n ');
|
||||
expect(stats.lines).toBe(0);
|
||||
expect(stats.words).toBe(0);
|
||||
});
|
||||
|
||||
it('单行内容', () => {
|
||||
const stats = getTextStats('hello world');
|
||||
expect(stats).toEqual({ chars: 11, words: 2, lines: 1 });
|
||||
});
|
||||
|
||||
it('多行非空内容', () => {
|
||||
const stats = getTextStats('line one\nline two\nline three');
|
||||
expect(stats.lines).toBe(3);
|
||||
expect(stats.words).toBe(6);
|
||||
expect(stats.chars).toBe(28); // 8+1+8+1+10
|
||||
});
|
||||
|
||||
it('空行不计数', () => {
|
||||
const stats = getTextStats('hello\n\n\nworld');
|
||||
expect(stats.lines).toBe(2);
|
||||
expect(stats.words).toBe(2);
|
||||
});
|
||||
|
||||
it('null / 非字符串 → 默认值', () => {
|
||||
expect(getTextStats(null)).toEqual({ chars: 0, words: 0, lines: 0 });
|
||||
expect(getTextStats(42)).toEqual({ chars: 0, words: 0, lines: 0 });
|
||||
});
|
||||
|
||||
it('CJK 内容', () => {
|
||||
const stats = getTextStats('你好世界\n欢迎使用');
|
||||
expect(stats.words).toBe(8);
|
||||
expect(stats.lines).toBe(2);
|
||||
expect(stats.chars).toBe('你好世界\n欢迎使用'.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatStatusStats', () => {
|
||||
it('lines > 0 → 「N 词 · M 行」', () => {
|
||||
expect(formatStatusStats({ words: 100, lines: 5 })).toBe('100 词 · 5 行');
|
||||
});
|
||||
|
||||
it('lines === 0 → 「N 词」', () => {
|
||||
expect(formatStatusStats({ words: 100, lines: 0 })).toBe('100 词');
|
||||
});
|
||||
|
||||
it('千分位分隔(zh-CN locale)', () => {
|
||||
expect(formatStatusStats({ words: 1234, lines: 5 })).toBe('1,234 词 · 5 行');
|
||||
expect(formatStatusStats({ words: 12345, lines: 5 })).toBe('12,345 词 · 5 行');
|
||||
});
|
||||
|
||||
it('0 词 → 「0 词」', () => {
|
||||
expect(formatStatusStats({ words: 0, lines: 0 })).toBe('0 词');
|
||||
});
|
||||
|
||||
it('缺字段时 fallback', () => {
|
||||
expect(formatStatusStats({})).toBe('0 词');
|
||||
expect(formatStatusStats({ words: 10 })).toBe('10 词');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user