test: increase coverage for document.dart
This commit is contained in:
parent
4daaaf0cc3
commit
b2f6c9c206
2 changed files with 124 additions and 9 deletions
|
|
@ -2,16 +2,40 @@ import 'dart:collection';
|
||||||
|
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
|
||||||
/// [Document] represents a AppFlowy Editor document structure.
|
/// [Document] represents an AppFlowy Editor document structure.
|
||||||
///
|
///
|
||||||
/// It stores the root of the document.
|
/// It stores the root of the document.
|
||||||
///
|
///
|
||||||
/// DO NOT directly mutate the properties of a [Document] object.
|
/// **DO NOT** directly mutate the properties of a [Document] object.
|
||||||
|
///
|
||||||
class Document {
|
class Document {
|
||||||
Document({
|
Document({
|
||||||
required this.root,
|
required this.root,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Constructs a [Document] from a JSON strcuture.
|
||||||
|
///
|
||||||
|
/// _Example of a [Document] in JSON format:_
|
||||||
|
/// ```
|
||||||
|
/// {
|
||||||
|
/// 'document': {
|
||||||
|
/// 'type': 'page',
|
||||||
|
/// 'children': [
|
||||||
|
/// {
|
||||||
|
/// 'type': 'paragraph',
|
||||||
|
/// 'data': {
|
||||||
|
/// 'delta': [
|
||||||
|
/// { 'insert': 'Welcome ' },
|
||||||
|
/// { 'insert': 'to ' },
|
||||||
|
/// { 'insert': 'AppFlowy!' }
|
||||||
|
/// ]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
factory Document.fromJson(Map<String, dynamic> json) {
|
factory Document.fromJson(Map<String, dynamic> json) {
|
||||||
assert(json['document'] is Map);
|
assert(json['document'] is Map);
|
||||||
|
|
||||||
|
|
@ -32,6 +56,11 @@ class Document {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a blank [Document] containing an empty root [Node].
|
||||||
|
///
|
||||||
|
/// If [withInitialText] is true, the document will contain an empty
|
||||||
|
/// paragraph [Node].
|
||||||
|
///
|
||||||
factory Document.blank({bool withInitialText = false}) {
|
factory Document.blank({bool withInitialText = false}) {
|
||||||
final root = Node(
|
final root = Node(
|
||||||
type: 'page',
|
type: 'page',
|
||||||
|
|
@ -42,12 +71,13 @@ class Document {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The root [Node] of the [Document]
|
||||||
final Node root;
|
final Node root;
|
||||||
|
|
||||||
/// first node of the document.
|
/// First node of the document.
|
||||||
Node? get first => root.children.first;
|
Node? get first => root.children.first;
|
||||||
|
|
||||||
/// last node of the document.
|
/// Last node of the document.
|
||||||
Node? get last {
|
Node? get last {
|
||||||
var last = root.children.last;
|
var last = root.children.last;
|
||||||
while (last.children.isNotEmpty) {
|
while (last.children.isNotEmpty) {
|
||||||
|
|
@ -133,6 +163,9 @@ class Document {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the root [Node] does not contain
|
||||||
|
/// any text.
|
||||||
|
///
|
||||||
bool get isEmpty {
|
bool get isEmpty {
|
||||||
if (root.children.isEmpty) {
|
if (root.children.isEmpty) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -151,6 +184,8 @@ class Document {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encodes the [Document] into a JSON structure.
|
||||||
|
///
|
||||||
Map<String, Object> toJson() {
|
Map<String, Object> toJson() {
|
||||||
return {
|
return {
|
||||||
'document': root.toJson(),
|
'document': root.toJson(),
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,16 @@ void main() async {
|
||||||
|
|
||||||
final node0 = Node(type: '0');
|
final node0 = Node(type: '0');
|
||||||
final node1 = Node(type: '1');
|
final node1 = Node(type: '1');
|
||||||
|
final node2 = Node(type: '2');
|
||||||
expect(document.insert([0], [node0, node1]), true);
|
expect(document.insert([0], [node0, node1]), true);
|
||||||
expect(document.nodeAtPath([0])?.type, '0');
|
expect(document.nodeAtPath([0])?.type, '0');
|
||||||
expect(document.nodeAtPath([1])?.type, '1');
|
expect(document.nodeAtPath([1])?.type, '1');
|
||||||
|
|
||||||
|
// Insert with an existing node at path
|
||||||
|
expect(document.insert([0], [node2]), true);
|
||||||
|
expect(document.nodeAtPath([0])?.type, '2');
|
||||||
|
expect(document.nodeAtPath([1])?.type, '0');
|
||||||
|
expect(document.nodeAtPath([2])?.type, '1');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('delete', () {
|
test('delete', () {
|
||||||
|
|
@ -32,14 +39,20 @@ void main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('update', () {
|
test('update', () {
|
||||||
|
final firstRootAttr = {'b': 'c'};
|
||||||
|
|
||||||
final node = Node(type: 'example', attributes: {'a': 'a'});
|
final node = Node(type: 'example', attributes: {'a': 'a'});
|
||||||
final document = Document(root: Node(type: 'root'));
|
final document =
|
||||||
|
Document(root: Node(type: 'root', attributes: firstRootAttr));
|
||||||
document.insert([0], [node]);
|
document.insert([0], [node]);
|
||||||
|
|
||||||
final attributes = {
|
final rootAttributes = {'b': 'b'};
|
||||||
'a': 'b',
|
final attributes = {'a': 'b', 'b': 'c'};
|
||||||
'b': 'c',
|
|
||||||
};
|
// If path is empty, should update attributes of root node
|
||||||
|
expect(document.nodeAtPath([])?.attributes, firstRootAttr);
|
||||||
|
expect(document.update([], rootAttributes), true);
|
||||||
|
expect(document.nodeAtPath([])?.attributes, rootAttributes);
|
||||||
|
|
||||||
expect(document.update([0], attributes), true);
|
expect(document.update([0], attributes), true);
|
||||||
expect(document.nodeAtPath([0])?.attributes, attributes);
|
expect(document.nodeAtPath([0])?.attributes, attributes);
|
||||||
|
|
@ -140,4 +153,71 @@ void main() async {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('first', () {
|
||||||
|
const firstLine = 'Welcome to AppFlowy!';
|
||||||
|
|
||||||
|
final document = Document.fromJson({
|
||||||
|
'document': {
|
||||||
|
'type': 'page',
|
||||||
|
'children': [
|
||||||
|
{
|
||||||
|
'type': 'paragraph',
|
||||||
|
'data': {
|
||||||
|
'delta': [
|
||||||
|
{'insert': firstLine}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final first = document.first;
|
||||||
|
|
||||||
|
expect(first!.delta!.toPlainText(), firstLine);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('last', () {
|
||||||
|
const firstLine = 'Welcome to AppFlowy!';
|
||||||
|
const firstChild = 'Hello';
|
||||||
|
const secondChild = 'World';
|
||||||
|
|
||||||
|
final document = Document.fromJson({
|
||||||
|
'document': {
|
||||||
|
'type': 'page',
|
||||||
|
'children': [
|
||||||
|
{
|
||||||
|
'type': 'paragraph',
|
||||||
|
'data': {
|
||||||
|
'delta': [
|
||||||
|
{'insert': firstLine}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'children': [
|
||||||
|
{
|
||||||
|
'type': 'paragraph',
|
||||||
|
'data': {
|
||||||
|
'delta': [
|
||||||
|
{'insert': firstChild}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'paragraph',
|
||||||
|
'data': {
|
||||||
|
'delta': [
|
||||||
|
{'insert': secondChild}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final last = document.last!;
|
||||||
|
expect(last.delta!.toPlainText(), secondChild);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue