281 lines
8 KiB
Dart
281 lines
8 KiB
Dart
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'utils.dart';
|
|
|
|
void main() => defineTests();
|
|
|
|
void defineTests() {
|
|
group(
|
|
'structure',
|
|
() {
|
|
testWidgets(
|
|
'footnote is detected and handle correctly',
|
|
(WidgetTester tester) async {
|
|
const String data = 'Foo[^a]\n[^a]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
expectTextStrings(widgets, <String>[
|
|
'Foo1',
|
|
'1.',
|
|
'Bar ↩',
|
|
]);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'footnote is detected and handle correctly for selectable markdown',
|
|
(WidgetTester tester) async {
|
|
const String data = 'Foo[^a]\n[^a]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
selectable: true,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
expectTextStrings(widgets, <String>[
|
|
'Foo1',
|
|
'1.',
|
|
'Bar ↩',
|
|
]);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'ignore footnotes without description',
|
|
(WidgetTester tester) async {
|
|
const String data = 'Foo[^1] Bar[^2]\n[^1]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
expectTextStrings(widgets, <String>[
|
|
'Foo1 Bar[^2]',
|
|
'1.',
|
|
'Bar ↩',
|
|
]);
|
|
},
|
|
);
|
|
testWidgets(
|
|
'ignore superscripts and footnotes order',
|
|
(WidgetTester tester) async {
|
|
const String data = '[^2]: Bar \n [^1]: Foo \n Foo[^f] Bar[^b]';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
expectTextStrings(widgets, <String>[
|
|
'Foo1 Bar2',
|
|
'1.',
|
|
'Foo ↩',
|
|
'2.',
|
|
'Bar ↩',
|
|
]);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'handle two digits superscript',
|
|
(WidgetTester tester) async {
|
|
const String data = '''
|
|
1[^1] 2[^2] 3[^3] 4[^4] 5[^5] 6[^6] 7[^7] 8[^8] 9[^9] 10[^10]
|
|
[^1]:1
|
|
[^2]:2
|
|
[^3]:3
|
|
[^4]:4
|
|
[^5]:5
|
|
[^6]:6
|
|
[^7]:7
|
|
[^8]:8
|
|
[^9]:9
|
|
[^10]:10
|
|
''';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
expectTextStrings(widgets, <String>[
|
|
'11 22 33 44 55 66 77 88 99 1010',
|
|
'1.',
|
|
'1 ↩',
|
|
'2.',
|
|
'2 ↩',
|
|
'3.',
|
|
'3 ↩',
|
|
'4.',
|
|
'4 ↩',
|
|
'5.',
|
|
'5 ↩',
|
|
'6.',
|
|
'6 ↩',
|
|
'7.',
|
|
'7 ↩',
|
|
'8.',
|
|
'8 ↩',
|
|
'9.',
|
|
'9 ↩',
|
|
'10.',
|
|
'10 ↩',
|
|
]);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
|
|
group(
|
|
'superscript textstyle replacing',
|
|
() {
|
|
testWidgets(
|
|
'superscript has correct default fontfeature',
|
|
(WidgetTester tester) async {
|
|
const String data = 'Foo[^a]\n[^a]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
final Text text = widgets.firstWhere((Widget widget) => widget is Text) as Text;
|
|
|
|
final TextSpan span = text.textSpan! as TextSpan;
|
|
final List<InlineSpan>? children = span.children;
|
|
|
|
expect(children, isNotNull);
|
|
expect(children!.length, 2);
|
|
expect(children[1].style, isNotNull);
|
|
expect(children[1].style!.fontFeatures?.length, 1);
|
|
expect(children[1].style!.fontFeatures?.first.feature, 'sups');
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'superscript has correct custom fontfeature',
|
|
(WidgetTester tester) async {
|
|
const String data = 'Foo[^a]\n[^a]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
MarkdownBody(
|
|
data: data,
|
|
styleSheet: MarkdownStyleSheet(superscriptFontFeatureTag: 'numr'),
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
final Text text = widgets.firstWhere((Widget widget) => widget is Text) as Text;
|
|
|
|
final TextSpan span = text.textSpan! as TextSpan;
|
|
final List<InlineSpan>? children = span.children;
|
|
|
|
expect(children, isNotNull);
|
|
expect(children!.length, 2);
|
|
expect(children[1].style, isNotNull);
|
|
expect(children[1].style!.fontFeatures?.length, 2);
|
|
expect(children[1].style!.fontFeatures?[1].feature, 'numr');
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'superscript index has the same font style like text',
|
|
(WidgetTester tester) async {
|
|
const String data = '# Foo[^a]\n[^a]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
const MarkdownBody(
|
|
data: data,
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
final Text text = widgets.firstWhere((Widget widget) => widget is Text) as Text;
|
|
|
|
final TextSpan span = text.textSpan! as TextSpan;
|
|
final List<InlineSpan>? children = span.children;
|
|
|
|
expect(children![0].style, isNotNull);
|
|
expect(children[1].style!.fontSize, children[0].style!.fontSize);
|
|
expect(children[1].style!.fontFamily, children[0].style!.fontFamily);
|
|
expect(children[1].style!.fontStyle, children[0].style!.fontStyle);
|
|
expect(children[1].style!.fontSize, children[0].style!.fontSize);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'link is correctly copied to new superscript index',
|
|
(WidgetTester tester) async {
|
|
final List<MarkdownLink> linkTapResults = <MarkdownLink>[];
|
|
const String data = 'Foo[^a]\n[^a]: Bar';
|
|
await tester.pumpWidget(
|
|
boilerplate(
|
|
MarkdownBody(
|
|
data: data,
|
|
onTapLink: (String text, String? href, String title) =>
|
|
linkTapResults.add(MarkdownLink(text, href, title)),
|
|
),
|
|
),
|
|
);
|
|
|
|
final Iterable<Widget> widgets = tester.allWidgets;
|
|
final Text text = widgets.firstWhere((Widget widget) => widget is Text) as Text;
|
|
|
|
final TextSpan span = text.textSpan! as TextSpan;
|
|
|
|
final List<Type> gestureRecognizerTypes = <Type>[];
|
|
span.visitChildren((InlineSpan inlineSpan) {
|
|
if (inlineSpan is TextSpan) {
|
|
final TapGestureRecognizer? recognizer = inlineSpan.recognizer as TapGestureRecognizer?;
|
|
gestureRecognizerTypes.add(recognizer?.runtimeType ?? Null);
|
|
if (recognizer != null) {
|
|
recognizer.onTap!();
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
|
|
expect(span.children!.length, 2);
|
|
expect(
|
|
gestureRecognizerTypes,
|
|
orderedEquals(<Type>[Null, TapGestureRecognizer]),
|
|
);
|
|
expectLinkTap(linkTapResults[0], const MarkdownLink('1', '#fn-a'));
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|