285 lines
10 KiB
Dart
285 lines
10 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
||
import 'package:yx_app_upgrade_flutter/app_upgrade_simple.dart';
|
||
|
||
void main() {
|
||
group('parseUpdateContent', () {
|
||
test('extracts header block and preserves nested markers', () {
|
||
const content = '''
|
||
/{
|
||
本次 **V2.2.0** 版本聚焦[使用体验]优化。
|
||
__支持嵌套__,例如 **[特别注意]** 与 `version 2.0`
|
||
/}
|
||
1. 第一条说明
|
||
2. 第二条说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(
|
||
parsed.header,
|
||
'本次 **V2.2.0** 版本聚焦[使用体验]优化。\n__支持嵌套__,例如 **[特别注意]** 与 `version 2.0`',
|
||
);
|
||
expect(parsed.bodyItems, hasLength(2));
|
||
expect(parsed.bodyItems.first.text, '1. 第一条说明');
|
||
expect(parsed.bodyItems.first.hasLeadingMarker, isTrue);
|
||
expect(parsed.bodyItems.last.text, '2. 第二条说明');
|
||
});
|
||
|
||
test('supports inline header block', () {
|
||
const content = '''
|
||
/{ 更新内容如下: /}
|
||
- 第一条说明
|
||
普通说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(parsed.header, '更新内容如下:');
|
||
expect(parsed.bodyItems, hasLength(2));
|
||
expect(parsed.bodyItems.first.hasLeadingMarker, isTrue);
|
||
expect(parsed.bodyItems.last.hasLeadingMarker, isFalse);
|
||
});
|
||
|
||
test('supports explicit but empty header block', () {
|
||
const content = '''
|
||
/{ /}
|
||
正文说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(parsed.header, isNull);
|
||
expect(parsed.bodyItems, hasLength(1));
|
||
expect(parsed.bodyItems.first.text, '正文说明');
|
||
});
|
||
|
||
test('keeps original content when header block is missing', () {
|
||
const content = '''
|
||
**重要内容**
|
||
第二行说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isFalse);
|
||
expect(parsed.header, isNull);
|
||
expect(parsed.bodyItems, hasLength(2));
|
||
expect(parsed.bodyItems.first.text, '**重要内容**');
|
||
expect(parsed.bodyItems.last.text, '第二行说明');
|
||
});
|
||
|
||
test('preserves blank lines inside header block', () {
|
||
const content = '''
|
||
/{
|
||
第一段说明
|
||
|
||
第二段说明
|
||
/}
|
||
正文说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(parsed.header, '第一段说明\n\n第二段说明');
|
||
expect(parsed.bodyItems, hasLength(1));
|
||
expect(parsed.bodyItems.first.text, '正文说明');
|
||
});
|
||
|
||
test('falls back to original content when header block is not closed', () {
|
||
const content = '''
|
||
/{
|
||
第一段说明
|
||
正文说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isFalse);
|
||
expect(parsed.header, isNull);
|
||
expect(parsed.bodyItems, hasLength(3));
|
||
expect(parsed.bodyItems[0].text, '/{');
|
||
expect(parsed.bodyItems[1].text, '第一段说明');
|
||
expect(parsed.bodyItems[2].text, '正文说明');
|
||
});
|
||
|
||
test('supports trailing body text on the same line as header end marker',
|
||
() {
|
||
const content = '''
|
||
/{ 头部说明 /} 1. 第一条说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(parsed.header, '头部说明');
|
||
expect(parsed.bodyItems, hasLength(1));
|
||
expect(parsed.bodyItems.first.text, '1. 第一条说明');
|
||
expect(parsed.bodyItems.first.hasLeadingMarker, isTrue);
|
||
});
|
||
|
||
test('normalizes windows line endings', () {
|
||
const content = '/{\r\n头部说明\r\n/}\r\n- 第一条\r\n普通说明\r\n';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(parsed.header, '头部说明');
|
||
expect(parsed.bodyItems, hasLength(2));
|
||
expect(parsed.bodyItems.first.text, '- 第一条');
|
||
expect(parsed.bodyItems.last.text, '普通说明');
|
||
});
|
||
|
||
test('detects multiple supported leading marker styles', () {
|
||
const content = '''
|
||
1. 数字序号
|
||
一、中文序号
|
||
- 无序列表
|
||
• 特殊符号列表
|
||
普通段落
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isFalse);
|
||
expect(parsed.bodyItems, hasLength(5));
|
||
expect(parsed.bodyItems[0].hasLeadingMarker, isTrue);
|
||
expect(parsed.bodyItems[1].hasLeadingMarker, isTrue);
|
||
expect(parsed.bodyItems[2].hasLeadingMarker, isTrue);
|
||
expect(parsed.bodyItems[3].hasLeadingMarker, isTrue);
|
||
expect(parsed.bodyItems[4].hasLeadingMarker, isFalse);
|
||
});
|
||
|
||
test('does not treat later header markers inside body as header block', () {
|
||
const content = '''
|
||
普通说明
|
||
/{ 这不是头部 /}
|
||
第二行正文
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isFalse);
|
||
expect(parsed.header, isNull);
|
||
expect(parsed.bodyItems, hasLength(3));
|
||
expect(parsed.bodyItems[1].text, '/{ 这不是头部 /}');
|
||
});
|
||
|
||
test('returns empty result for blank content', () {
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(' \n \r\n ');
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isFalse);
|
||
expect(parsed.header, isNull);
|
||
expect(parsed.bodyItems, isEmpty);
|
||
});
|
||
|
||
test('keeps the final growth-center line as a separate body item', () {
|
||
const content = '''
|
||
/{本次 **V2.2.0** 版本围绕[使用体验]、[账号安全]、[家校联动]、[学习管理]等方面进行多项优化与功能新增,具体更新内容如下:/}
|
||
工作录入新增**草稿箱功能**,录入内容自动暂存,录入途中临时退出、意外关闭页面,都不会丢失填写数据,有效避免重复录入,提升使用效率;
|
||
优化**多账号登录机制**,若同一手机号绑定多个账号,登录时需手动选择本次要登录的对应账号,区分账号使用,保障使用精准性;
|
||
全新上线**家校互动板块**,新增家长会、社群运营、线上家访特色功能,搭建高效家校沟通渠道,助力家校协同共育;
|
||
**成长中心**全面调整优化:成长中心入口迁移至工作台页面,升级全局搜索能力,章节内容改为结构化排版展示;优化视频播放逻辑与播放限制规则,同时新增学习过程监管功能,强化学习管控。
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(
|
||
parsed.header,
|
||
'本次 **V2.2.0** 版本围绕[使用体验]、[账号安全]、[家校联动]、[学习管理]等方面进行多项优化与功能新增,具体更新内容如下:',
|
||
);
|
||
expect(parsed.bodyItems, hasLength(4));
|
||
expect(parsed.bodyItems[0].text, startsWith('工作录入新增**草稿箱功能**'));
|
||
expect(parsed.bodyItems[1].text, startsWith('优化**多账号登录机制**'));
|
||
expect(parsed.bodyItems[2].text, startsWith('全新上线**家校互动板块**'));
|
||
expect(
|
||
parsed.bodyItems[3].text,
|
||
'**成长中心**全面调整优化:成长中心入口迁移至工作台页面,升级全局搜索能力,章节内容改为结构化排版展示;优化视频播放逻辑与播放限制规则,同时新增学习过程监管功能,强化学习管控。',
|
||
);
|
||
});
|
||
|
||
test('does not treat bold marker at line start as list marker', () {
|
||
const content = '''
|
||
**成长中心**全面调整优化:成长中心入口迁移至工作台页面,升级全局搜索能力。
|
||
* 合法无序列表项
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.bodyItems, hasLength(2));
|
||
expect(parsed.bodyItems.first.text,
|
||
'**成长中心**全面调整优化:成长中心入口迁移至工作台页面,升级全局搜索能力。');
|
||
expect(parsed.bodyItems.first.hasLeadingMarker, isFalse);
|
||
expect(parsed.bodyItems.last.text, '* 合法无序列表项');
|
||
expect(parsed.bodyItems.last.hasLeadingMarker, isTrue);
|
||
});
|
||
|
||
test(
|
||
'supports all rich text markers when they appear on the first body line',
|
||
() {
|
||
const content = '''
|
||
**粗体首行**
|
||
__斜体次行__
|
||
`代码第三行`
|
||
[高亮第四行]
|
||
**[组合重点]**
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isFalse);
|
||
expect(parsed.bodyItems, hasLength(5));
|
||
expect(parsed.bodyItems[0].text, '**粗体首行**');
|
||
expect(parsed.bodyItems[1].text, '__斜体次行__');
|
||
expect(parsed.bodyItems[2].text, '`代码第三行`');
|
||
expect(parsed.bodyItems[3].text, '[高亮第四行]');
|
||
expect(parsed.bodyItems[4].text, '**[组合重点]**');
|
||
expect(
|
||
parsed.bodyItems.every((item) => item.hasLeadingMarker == false),
|
||
isTrue,
|
||
);
|
||
});
|
||
|
||
test('supports rich text markers on the first line inside header block',
|
||
() {
|
||
const content = '''
|
||
/{
|
||
**头部粗体**
|
||
__[头部高亮斜体]__
|
||
`头部代码`
|
||
/}
|
||
正文说明
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.hasExplicitHeaderBlock, isTrue);
|
||
expect(
|
||
parsed.header,
|
||
'**头部粗体**\n__[头部高亮斜体]__\n`头部代码`',
|
||
);
|
||
expect(parsed.bodyItems, hasLength(1));
|
||
expect(parsed.bodyItems.first.text, '正文说明');
|
||
});
|
||
|
||
test('does not treat version-like prefix as ordered marker', () {
|
||
const content = '''
|
||
1.0版本修复说明
|
||
2. 第一条真正的序号内容
|
||
''';
|
||
|
||
final parsed = AppUpgradeSimple.parseUpdateContent(content);
|
||
|
||
expect(parsed.bodyItems, hasLength(2));
|
||
expect(parsed.bodyItems.first.text, '1.0版本修复说明');
|
||
expect(parsed.bodyItems.first.hasLeadingMarker, isFalse);
|
||
expect(parsed.bodyItems.last.text, '2. 第一条真正的序号内容');
|
||
expect(parsed.bodyItems.last.hasLeadingMarker, isTrue);
|
||
});
|
||
});
|
||
}
|