mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #878 from LucasXu0/logger_refactor
feat: [improvements] integrate logging library in AppFlowyEditor
This commit is contained in:
commit
1d2dd15142
@ -97,9 +97,13 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final data = Map<String, Object>.from(json.decode(snapshot.data!));
|
||||
return _buildAppFlowyEditor(EditorState(
|
||||
document: StateTree.fromJson(data),
|
||||
));
|
||||
final editorState = EditorState(document: StateTree.fromJson(data));
|
||||
editorState.logConfiguration
|
||||
..level = LogLevel.all
|
||||
..handler = (message) {
|
||||
debugPrint(message);
|
||||
};
|
||||
return _buildAppFlowyEditor(editorState);
|
||||
} else {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
|
@ -1,6 +1,7 @@
|
||||
/// AppFlowyEditor library
|
||||
library appflowy_editor;
|
||||
|
||||
export 'src/infra/log.dart';
|
||||
export 'src/document/node.dart';
|
||||
export 'src/document/path.dart';
|
||||
export 'src/document/position.dart';
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:appflowy_editor/src/service/service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -48,10 +49,15 @@ class EditorState {
|
||||
// Service reference.
|
||||
final service = FlowyService();
|
||||
|
||||
/// Configures log output parameters,
|
||||
/// such as log level and log output callbacks,
|
||||
/// with this variable.
|
||||
LogConfiguration get logConfiguration => LogConfiguration();
|
||||
|
||||
final UndoManager undoManager = UndoManager();
|
||||
Selection? _cursorSelection;
|
||||
|
||||
/// TODO: only for testing.
|
||||
// TODO: only for testing.
|
||||
bool disableSealTimer = false;
|
||||
|
||||
Selection? get cursorSelection {
|
||||
@ -120,7 +126,7 @@ class EditorState {
|
||||
_debouncedSealHistoryItemTimer =
|
||||
Timer(const Duration(milliseconds: 1000), () {
|
||||
if (undoManager.undoStack.isNonEmpty) {
|
||||
debugPrint('Seal history item');
|
||||
Log.editor.debug('Seal history item');
|
||||
final last = undoManager.undoStack.last;
|
||||
last.seal();
|
||||
}
|
||||
|
@ -0,0 +1,138 @@
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
enum LogLevel {
|
||||
off,
|
||||
error,
|
||||
warn,
|
||||
info,
|
||||
debug,
|
||||
all,
|
||||
}
|
||||
|
||||
typedef LogHandler = void Function(String message);
|
||||
|
||||
/// Manages log service for [AppFlowyEditor]
|
||||
///
|
||||
/// Set the log level and config the handler depending on your need.
|
||||
class LogConfiguration {
|
||||
LogConfiguration._() {
|
||||
Logger.root.onRecord.listen((record) {
|
||||
if (handler != null) {
|
||||
handler!(
|
||||
'[${record.level.toLogLevel().name}][${record.loggerName}]: ${record.time}: ${record.message}',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
factory LogConfiguration() => _logConfiguration;
|
||||
|
||||
static final LogConfiguration _logConfiguration = LogConfiguration._();
|
||||
|
||||
LogHandler? handler;
|
||||
|
||||
LogLevel _level = LogLevel.off;
|
||||
|
||||
LogLevel get level => _level;
|
||||
set level(LogLevel level) {
|
||||
_level = level;
|
||||
Logger.root.level = level.toLevel();
|
||||
}
|
||||
}
|
||||
|
||||
/// For logging message in AppFlowyEditor
|
||||
class Log {
|
||||
Log._({
|
||||
required this.name,
|
||||
}) : _logger = Logger(name);
|
||||
|
||||
final String name;
|
||||
late final Logger _logger;
|
||||
|
||||
/// For logging message related to [AppFlowyEditor].
|
||||
///
|
||||
/// For example, uses the logger when registering plugins
|
||||
/// or handling something related to [EditorState].
|
||||
static Log editor = Log._(name: 'editor');
|
||||
|
||||
/// For logging message related to [AppFlowySelectionService].
|
||||
///
|
||||
/// For example, uses the logger when updating or clearing selection.
|
||||
static Log selection = Log._(name: 'selection');
|
||||
|
||||
/// For logging message related to [AppFlowyKeyboardService].
|
||||
///
|
||||
/// For example, uses the logger when processing shortcut events.
|
||||
static Log keyboard = Log._(name: 'keyboard');
|
||||
|
||||
/// For logging message related to [AppFlowyInputService].
|
||||
///
|
||||
/// For example, uses the logger when processing text inputs.
|
||||
static Log input = Log._(name: 'input');
|
||||
|
||||
/// For logging message related to [AppFlowyScrollService].
|
||||
///
|
||||
/// For example, uses the logger when processing scroll events.
|
||||
static Log scroll = Log._(name: 'scroll');
|
||||
|
||||
/// For logging message related to UI.
|
||||
///
|
||||
/// For example, uses the logger when building the widget.
|
||||
static Log ui = Log._(name: 'ui');
|
||||
|
||||
void error(String message) => _logger.severe(message);
|
||||
void warn(String message) => _logger.warning(message);
|
||||
void info(String message) => _logger.info(message);
|
||||
void debug(String message) => _logger.fine(message);
|
||||
}
|
||||
|
||||
extension on LogLevel {
|
||||
Level toLevel() {
|
||||
switch (this) {
|
||||
case LogLevel.off:
|
||||
return Level.OFF;
|
||||
case LogLevel.error:
|
||||
return Level.SEVERE;
|
||||
case LogLevel.warn:
|
||||
return Level.WARNING;
|
||||
case LogLevel.info:
|
||||
return Level.INFO;
|
||||
case LogLevel.debug:
|
||||
return Level.FINE;
|
||||
case LogLevel.all:
|
||||
return Level.ALL;
|
||||
}
|
||||
}
|
||||
|
||||
String get name {
|
||||
switch (this) {
|
||||
case LogLevel.off:
|
||||
return 'OFF';
|
||||
case LogLevel.error:
|
||||
return 'ERROR';
|
||||
case LogLevel.warn:
|
||||
return 'WARN';
|
||||
case LogLevel.info:
|
||||
return 'INFO';
|
||||
case LogLevel.debug:
|
||||
return 'DEBUG';
|
||||
case LogLevel.all:
|
||||
return 'ALL';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension on Level {
|
||||
LogLevel toLogLevel() {
|
||||
if (this == Level.SEVERE) {
|
||||
return LogLevel.error;
|
||||
} else if (this == Level.WARNING) {
|
||||
return LogLevel.warn;
|
||||
} else if (this == Level.INFO) {
|
||||
return LogLevel.info;
|
||||
} else if (this == Level.FINE) {
|
||||
return LogLevel.debug;
|
||||
}
|
||||
return LogLevel.off;
|
||||
}
|
||||
}
|
@ -83,7 +83,6 @@ class _CheckboxNodeWidgetState extends State<CheckboxNodeWidget>
|
||||
name: check ? 'check' : 'uncheck',
|
||||
),
|
||||
onTap: () {
|
||||
debugPrint('[Checkbox] onTap...');
|
||||
TransactionBuilder(widget.editorState)
|
||||
..updateNode(widget.textNode, {
|
||||
StyleKey.checkbox: !check,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@ -243,7 +244,8 @@ class _AppFlowyInputState extends State<AppFlowyInput>
|
||||
|
||||
@override
|
||||
void updateEditingValueWithDeltas(List<TextEditingDelta> textEditingDeltas) {
|
||||
debugPrint(textEditingDeltas.map((delta) => delta.toString()).toString());
|
||||
Log.input
|
||||
.debug(textEditingDeltas.map((delta) => delta.toString()).toString());
|
||||
|
||||
apply(textEditingDeltas);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/infra/html_converter.dart';
|
||||
import 'package:appflowy_editor/src/document/node_iterator.dart';
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rich_clipboard/rich_clipboard.dart';
|
||||
@ -19,10 +20,10 @@ _handleCopy(EditorState editorState) async {
|
||||
startOffset: selection.start.offset,
|
||||
endOffset: selection.end.offset)
|
||||
.toHTMLString();
|
||||
debugPrint('copy html: $htmlString');
|
||||
Log.keyboard.debug('copy html: $htmlString');
|
||||
RichClipboard.setData(RichClipboardData(html: htmlString));
|
||||
} else {
|
||||
debugPrint("unimplemented: copy non-text");
|
||||
Log.keyboard.debug('unimplemented: copy non-text');
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -37,7 +38,7 @@ _handleCopy(EditorState editorState) async {
|
||||
startOffset: selection.start.offset,
|
||||
endOffset: selection.end.offset)
|
||||
.toHTMLString();
|
||||
debugPrint('copy html: $copyString');
|
||||
Log.keyboard.debug('copy html: $copyString');
|
||||
RichClipboard.setData(RichClipboardData(html: copyString));
|
||||
}
|
||||
|
||||
@ -54,7 +55,7 @@ _pasteHTML(EditorState editorState, String html) {
|
||||
return;
|
||||
}
|
||||
|
||||
debugPrint('paste html: $html');
|
||||
Log.keyboard.debug('paste html: $html');
|
||||
final nodes = HTMLToNodesConverter(html).toNodes();
|
||||
|
||||
if (nodes.isEmpty) {
|
||||
@ -250,7 +251,6 @@ _handlePastePlainText(EditorState editorState, String plainText) {
|
||||
/// 1. copy the selected content
|
||||
/// 2. delete selected content
|
||||
_handleCut(EditorState editorState) {
|
||||
debugPrint('cut');
|
||||
_handleCopy(editorState);
|
||||
_deleteSelectedContent(editorState);
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ KeyEventResult _handleDelete(EditorState editorState, RawKeyEvent event) {
|
||||
if (textNodes.length == 1) {
|
||||
final textNode = textNodes.first;
|
||||
if (selection.start.offset >= textNode.delta.length) {
|
||||
debugPrint("merge next line");
|
||||
final nextNode = textNode.next;
|
||||
if (nextNode == null) {
|
||||
return KeyEventResult.ignored;
|
||||
|
@ -3,6 +3,7 @@ import 'dart:math';
|
||||
import 'package:appflowy_editor/src/document/node.dart';
|
||||
import 'package:appflowy_editor/src/editor_state.dart';
|
||||
import 'package:appflowy_editor/src/infra/flowy_svg.dart';
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
|
||||
import 'package:appflowy_editor/src/render/rich_text/rich_text_style.dart';
|
||||
import 'package:appflowy_editor/src/service/default_text_operations/format_rich_text_style.dart';
|
||||
@ -50,12 +51,6 @@ final List<PopupListItem> _popupListItems = [
|
||||
icon: _popupListIcon('bullets'),
|
||||
handler: (editorState) => insertBulletedListAfterSelection(editorState),
|
||||
),
|
||||
// PopupListItem(
|
||||
// text: 'Numbered list',
|
||||
// keywords: ['numbered list'],
|
||||
// icon: _popupListIcon('number'),
|
||||
// handler: (editorState) => debugPrint('Not implement yet!'),
|
||||
// ),
|
||||
PopupListItem(
|
||||
text: 'To-do List',
|
||||
keywords: ['checkbox', 'todo'],
|
||||
@ -293,7 +288,7 @@ class _PopupListWidgetState extends State<PopupListWidget> {
|
||||
}
|
||||
|
||||
KeyEventResult _onKey(FocusNode node, RawKeyEvent event) {
|
||||
debugPrint('slash on key $event');
|
||||
Log.keyboard.debug('slash command, on key $event');
|
||||
if (event is! RawKeyDownEvent) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
@ -94,15 +95,13 @@ class _AppFlowyKeyboardState extends State<AppFlowyKeyboard>
|
||||
|
||||
@override
|
||||
KeyEventResult onKey(RawKeyEvent event) {
|
||||
debugPrint('on keyboard event $event');
|
||||
Log.keyboard.debug('on keyboard event $event');
|
||||
|
||||
if (event is! RawKeyDownEvent) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
for (final handler in widget.handlers) {
|
||||
// debugPrint('handle keyboard event $event by $handler');
|
||||
|
||||
KeyEventResult result = handler(widget.editorState, event);
|
||||
|
||||
switch (result) {
|
||||
@ -119,7 +118,7 @@ class _AppFlowyKeyboardState extends State<AppFlowyKeyboard>
|
||||
}
|
||||
|
||||
void _onFocusChange(bool value) {
|
||||
debugPrint('[KeyBoard Service] focus change $value');
|
||||
Log.keyboard.debug('on keyboard event focus change $value');
|
||||
}
|
||||
|
||||
KeyEventResult _onKey(FocusNode node, RawKeyEvent event) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:appflowy_editor/src/document/node.dart';
|
||||
import 'package:appflowy_editor/src/editor_state.dart';
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@ -86,7 +87,7 @@ class AppFlowyRenderPlugin extends AppFlowyRenderPluginService {
|
||||
|
||||
@override
|
||||
void register(String name, NodeWidgetBuilder builder) {
|
||||
debugPrint('[Plugins] registering $name...');
|
||||
Log.editor.info('registers plugin($name)...');
|
||||
_validatePlugin(name);
|
||||
_builders[name] = builder;
|
||||
}
|
||||
@ -111,7 +112,7 @@ class AppFlowyRenderPlugin extends AppFlowyRenderPluginService {
|
||||
builder: (_, child) {
|
||||
return Consumer<TextNode>(
|
||||
builder: ((_, value, child) {
|
||||
debugPrint('Text Node is rebuilding...');
|
||||
Log.ui.debug('TextNode is rebuilding...');
|
||||
return builder.build(context);
|
||||
}),
|
||||
);
|
||||
@ -122,7 +123,7 @@ class AppFlowyRenderPlugin extends AppFlowyRenderPluginService {
|
||||
builder: (_, child) {
|
||||
return Consumer<Node>(
|
||||
builder: ((_, value, child) {
|
||||
debugPrint('Node is rebuilding...');
|
||||
Log.ui.debug('Node is rebuilding...');
|
||||
return builder.build(context);
|
||||
}),
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:appflowy_editor/src/extensions/object_extensions.dart';
|
||||
@ -113,13 +114,13 @@ class _AppFlowyScrollState extends State<AppFlowyScroll>
|
||||
@override
|
||||
void disable() {
|
||||
_scrollEnabled = false;
|
||||
debugPrint('[scroll] $_scrollEnabled');
|
||||
Log.scroll.debug('disable scroll service');
|
||||
}
|
||||
|
||||
@override
|
||||
void enable() {
|
||||
_scrollEnabled = true;
|
||||
debugPrint('[scroll] $_scrollEnabled');
|
||||
Log.scroll.debug('enable scroll service');
|
||||
}
|
||||
|
||||
void _onPointerSignal(PointerSignalEvent event) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy_editor/src/document/node.dart';
|
||||
@ -185,12 +186,12 @@ class _AppFlowySelectionState extends State<AppFlowySelection>
|
||||
|
||||
if (selection != null) {
|
||||
if (selection.isCollapsed) {
|
||||
/// updates cursor area.
|
||||
debugPrint('updating cursor, $selection');
|
||||
// updates cursor area.
|
||||
Log.selection.debug('update cursor area, $selection');
|
||||
_updateCursorAreas(selection.start);
|
||||
} else {
|
||||
// updates selection area.
|
||||
debugPrint('updating selection, $selection');
|
||||
Log.selection.debug('update cursor area, $selection');
|
||||
_updateSelectionAreas(selection);
|
||||
}
|
||||
}
|
||||
@ -312,14 +313,10 @@ class _AppFlowySelectionState extends State<AppFlowySelection>
|
||||
|
||||
// compute the selection in range.
|
||||
if (first != null && last != null) {
|
||||
bool isDownward = (identical(first, last))
|
||||
? panStartOffset.dx < panEndOffset.dx
|
||||
: panStartOffset.dy < panEndOffset.dy;
|
||||
final start =
|
||||
first.getSelectionInRange(panStartOffset, panEndOffset).start;
|
||||
final end = last.getSelectionInRange(panStartOffset, panEndOffset).end;
|
||||
final selection = Selection(start: start, end: end);
|
||||
debugPrint('[_onPanUpdate] isDownward = $isDownward, $selection');
|
||||
updateSelection(selection);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:appflowy_editor/src/document/selection.dart';
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:appflowy_editor/src/operation/operation.dart';
|
||||
import 'package:appflowy_editor/src/operation/transaction_builder.dart';
|
||||
import 'package:appflowy_editor/src/operation/transaction.dart';
|
||||
import 'package:appflowy_editor/src/editor_state.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// A [HistoryItem] contains list of operations committed by users.
|
||||
/// If a [HistoryItem] is not sealed, operations can be added sequentially.
|
||||
@ -112,7 +112,7 @@ class UndoManager {
|
||||
}
|
||||
|
||||
undo() {
|
||||
debugPrint('undo');
|
||||
Log.editor.debug('undo');
|
||||
final s = state;
|
||||
if (s == null) {
|
||||
return;
|
||||
@ -131,7 +131,7 @@ class UndoManager {
|
||||
}
|
||||
|
||||
redo() {
|
||||
debugPrint('redo');
|
||||
Log.editor.debug('redo');
|
||||
final s = state;
|
||||
if (s == null) {
|
||||
return;
|
||||
|
@ -16,6 +16,7 @@ dependencies:
|
||||
flutter_svg: ^1.1.1+1
|
||||
provider: ^6.0.3
|
||||
url_launcher: ^6.1.5
|
||||
logging: ^1.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -0,0 +1,169 @@
|
||||
import 'package:appflowy_editor/src/infra/log.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'test_editor.dart';
|
||||
|
||||
void main() async {
|
||||
group('log.dart', () {
|
||||
testWidgets('test LogConfiguration in EditorState', (tester) async {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
|
||||
final editor = tester.editor;
|
||||
editor.editorState.logConfiguration
|
||||
..level = LogLevel.all
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
expect(logs.last.contains('DEBUG'), true);
|
||||
expect(logs.length, 1);
|
||||
});
|
||||
|
||||
test('test LogLevel.all', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.all
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
expect(logs.last.contains('DEBUG'), true);
|
||||
Log.editor.info(text);
|
||||
expect(logs.last.contains('INFO'), true);
|
||||
Log.editor.warn(text);
|
||||
expect(logs.last.contains('WARN'), true);
|
||||
Log.editor.error(text);
|
||||
expect(logs.last.contains('ERROR'), true);
|
||||
|
||||
expect(logs.length, 4);
|
||||
});
|
||||
|
||||
test('test LogLevel.off', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.off
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
Log.editor.info(text);
|
||||
Log.editor.warn(text);
|
||||
Log.editor.error(text);
|
||||
|
||||
expect(logs.length, 0);
|
||||
});
|
||||
|
||||
test('test LogLevel.error', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.error
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
Log.editor.info(text);
|
||||
Log.editor.warn(text);
|
||||
Log.editor.error(text);
|
||||
|
||||
expect(logs.length, 1);
|
||||
});
|
||||
|
||||
test('test LogLevel.warn', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.warn
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
Log.editor.info(text);
|
||||
Log.editor.warn(text);
|
||||
Log.editor.error(text);
|
||||
|
||||
expect(logs.length, 2);
|
||||
});
|
||||
|
||||
test('test LogLevel.info', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.info
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
Log.editor.info(text);
|
||||
Log.editor.warn(text);
|
||||
Log.editor.error(text);
|
||||
|
||||
expect(logs.length, 3);
|
||||
});
|
||||
|
||||
test('test LogLevel.debug', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.debug
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
Log.editor.info(text);
|
||||
Log.editor.warn(text);
|
||||
Log.editor.error(text);
|
||||
|
||||
expect(logs.length, 4);
|
||||
});
|
||||
|
||||
test('test logger', () {
|
||||
const text = 'Welcome to Appflowy 😁';
|
||||
|
||||
final List<String> logs = [];
|
||||
LogConfiguration()
|
||||
..level = LogLevel.all
|
||||
..handler = (message) {
|
||||
logs.add(message);
|
||||
};
|
||||
|
||||
Log.editor.debug(text);
|
||||
expect(logs.last.contains('editor'), true);
|
||||
|
||||
Log.selection.debug(text);
|
||||
expect(logs.last.contains('selection'), true);
|
||||
|
||||
Log.keyboard.debug(text);
|
||||
expect(logs.last.contains('keyboard'), true);
|
||||
|
||||
Log.input.debug(text);
|
||||
expect(logs.last.contains('input'), true);
|
||||
|
||||
Log.scroll.debug(text);
|
||||
expect(logs.last.contains('scroll'), true);
|
||||
|
||||
Log.ui.debug(text);
|
||||
expect(logs.last.contains('ui'), true);
|
||||
|
||||
expect(logs.length, 6);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user