| // Copyright 2017 The Chromium 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 'dart:convert'; |
| import 'dart:ui'; |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| class TestTree extends Object with DiagnosticableTreeMixin { |
| TestTree({ |
| this.name, |
| this.style, |
| this.children = const <TestTree>[], |
| this.properties = const <DiagnosticsNode>[], |
| }); |
| |
| final String name; |
| final List<TestTree> children; |
| final List<DiagnosticsNode> properties; |
| final DiagnosticsTreeStyle style; |
| |
| @override |
| List<DiagnosticsNode> debugDescribeChildren() { |
| final List<DiagnosticsNode> children = <DiagnosticsNode>[]; |
| for (TestTree child in this.children) { |
| children.add(child.toDiagnosticsNode( |
| name: 'child ${child.name}', |
| style: child.style, |
| )); |
| } |
| return children; |
| } |
| |
| @override |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| if (style != null) |
| properties.defaultDiagnosticsTreeStyle = style; |
| |
| this.properties.forEach(properties.add); |
| } |
| } |
| |
| enum ExampleEnum { |
| hello, |
| world, |
| deferToChild, |
| } |
| |
| /// Encode and decode to JSON to make sure all objects in the JSON for the |
| /// [DiagnosticsNode] are valid JSON. |
| Map<String, Object> simulateJsonSerialization(DiagnosticsNode node) { |
| return json.decode(json.encode(node.toJsonMap())); |
| } |
| |
| void validateNodeJsonSerialization(DiagnosticsNode node) { |
| validateNodeJsonSerializationHelper(simulateJsonSerialization(node), node); |
| } |
| |
| void validateNodeJsonSerializationHelper(Map<String, Object> json, DiagnosticsNode node) { |
| expect(json['name'], equals(node.name)); |
| expect(json['showSeparator'], equals(node.showSeparator)); |
| expect(json['description'], equals(node.toDescription())); |
| expect(json['level'], equals(describeEnum(node.level))); |
| expect(json['showName'], equals(node.showName)); |
| expect(json['emptyBodyDescription'], equals(node.emptyBodyDescription)); |
| expect(json['style'], equals(describeEnum(node.style))); |
| final String valueToString = node is DiagnosticsProperty ? node.valueToString() : node.value.toString(); |
| expect(json['valueToString'], equals(valueToString)); |
| expect(json['type'], equals(node.runtimeType.toString())); |
| expect(json['hasChildren'], equals(node.getChildren().isNotEmpty)); |
| } |
| |
| void validatePropertyJsonSerialization(DiagnosticsProperty<Object> property) { |
| validatePropertyJsonSerializationHelper(simulateJsonSerialization(property), property); |
| } |
| |
| void validateStringPropertyJsonSerialization(StringProperty property) { |
| final Map<String, Object> json = simulateJsonSerialization(property); |
| expect(json['quoted'], equals(property.quoted)); |
| validatePropertyJsonSerializationHelper(json, property); |
| } |
| |
| void validateFlagPropertyJsonSerialization(FlagProperty property) { |
| final Map<String, Object> json = simulateJsonSerialization(property); |
| expect(json['ifTrue'], equals(property.ifTrue)); |
| |
| if (property.ifTrue != null) { |
| expect(json['ifTrue'], equals(property.ifTrue)); |
| } else { |
| expect(json.containsKey('ifTrue'), isFalse); |
| } |
| |
| if (property.ifFalse != null) { |
| expect(json['ifFalse'], property.ifFalse); |
| } else { |
| expect(json.containsKey('isFalse'), isFalse); |
| } |
| validatePropertyJsonSerializationHelper(json, property); |
| } |
| |
| void validateDoublePropertyJsonSerialization(DoubleProperty property) { |
| final Map<String, Object> json = simulateJsonSerialization(property); |
| if (property.unit != null) { |
| expect(json['unit'], equals(property.unit)); |
| } else { |
| expect(json.containsKey('unit'), isFalse); |
| } |
| |
| expect(json['numberToString'], equals(property.numberToString())); |
| |
| validatePropertyJsonSerializationHelper(json, property); |
| } |
| |
| void validateObjectFlagPropertyJsonSerialization(ObjectFlagProperty<Object> property) { |
| final Map<String, Object> json = simulateJsonSerialization(property); |
| if (property.ifPresent != null) { |
| expect(json['ifPresent'], equals(property.ifPresent)); |
| } else { |
| expect(json.containsKey('ifPresent'), isFalse); |
| } |
| |
| validatePropertyJsonSerializationHelper(json, property); |
| } |
| |
| void validateIterablePropertyJsonSerialization(IterableProperty<Object> property) { |
| final Map<String, Object> json = simulateJsonSerialization(property); |
| if (property.value != null) { |
| final List<Object> valuesJson = json['values']; |
| final List<String> expectedValues = property.value.map<String>((Object value) => value.toString()).toList(); |
| expect(listEquals(valuesJson, expectedValues), isTrue); |
| } else { |
| expect(json.containsKey('values'), isFalse); |
| } |
| |
| validatePropertyJsonSerializationHelper(json, property); |
| } |
| |
| void validatePropertyJsonSerializationHelper(final Map<String, Object> json, DiagnosticsProperty<Object> property) { |
| if (property.defaultValue != kNoDefaultValue) { |
| expect(json['defaultValue'], equals(property.defaultValue.toString())); |
| } else { |
| expect(json.containsKey('defaultValue'), isFalse); |
| } |
| |
| if (property.ifEmpty != null) { |
| expect(json['ifEmpty'], equals(property.ifEmpty)); |
| } else { |
| expect(json.containsKey('ifEmpty'), isFalse); |
| } |
| if (property.ifNull != null) { |
| expect(json['ifNull'], equals(property.ifNull)); |
| } else { |
| expect(json.containsKey('ifNull'), isFalse); |
| } |
| |
| if (property.tooltip != null) { |
| expect(json['tooltip'], equals(property.tooltip)); |
| } else { |
| expect(json.containsKey('tooltip'), isFalse); |
| } |
| |
| expect(json['missingIfNull'], equals(property.missingIfNull)); |
| if (property.exception != null) { |
| expect(json['exception'], equals(property.exception.toString())); |
| } else { |
| expect(json.containsKey('exception'), isFalse); |
| } |
| expect(json['propertyType'], equals(property.propertyType.toString())); |
| expect(json['valueToString'], equals(property.valueToString())); |
| expect(json.containsKey('defaultLevel'), isTrue); |
| if (property.value is Diagnosticable) { |
| expect(json['isDiagnosticableValue'], isTrue); |
| } else { |
| expect(json.containsKey('isDiagnosticableValue'), isFalse); |
| } |
| validateNodeJsonSerializationHelper(json, property); |
| } |
| |
| void main() { |
| test('TreeDiagnosticsMixin control test', () async { |
| void goldenStyleTest(String description, |
| {DiagnosticsTreeStyle style, |
| DiagnosticsTreeStyle lastChildStyle, |
| String golden = ''}) { |
| final TestTree tree = TestTree(children: <TestTree>[ |
| TestTree(name: 'node A', style: style), |
| TestTree( |
| name: 'node B', |
| children: <TestTree>[ |
| TestTree(name: 'node B1', style: style), |
| TestTree(name: 'node B2', style: style), |
| TestTree(name: 'node B3', style: lastChildStyle ?? style), |
| ], |
| style: style, |
| ), |
| TestTree(name: 'node C', style: lastChildStyle ?? style), |
| ], style: lastChildStyle); |
| |
| expect(tree, hasAGoodToStringDeep); |
| expect( |
| tree.toDiagnosticsNode(style: style).toStringDeep(), |
| equalsIgnoringHashCodes(golden), |
| reason: description, |
| ); |
| validateNodeJsonSerialization(tree.toDiagnosticsNode()); |
| } |
| |
| goldenStyleTest( |
| 'dense', |
| style: DiagnosticsTreeStyle.dense, |
| golden: |
| 'TestTree#00000\n' |
| '├child node A: TestTree#00000\n' |
| '├child node B: TestTree#00000\n' |
| '│├child node B1: TestTree#00000\n' |
| '│├child node B2: TestTree#00000\n' |
| '│└child node B3: TestTree#00000\n' |
| '└child node C: TestTree#00000\n', |
| ); |
| |
| goldenStyleTest( |
| 'sparse', |
| style: DiagnosticsTreeStyle.sparse, |
| golden: |
| 'TestTree#00000\n' |
| ' ├─child node A: TestTree#00000\n' |
| ' ├─child node B: TestTree#00000\n' |
| ' │ ├─child node B1: TestTree#00000\n' |
| ' │ ├─child node B2: TestTree#00000\n' |
| ' │ └─child node B3: TestTree#00000\n' |
| ' └─child node C: TestTree#00000\n', |
| ); |
| |
| goldenStyleTest( |
| 'dashed', |
| style: DiagnosticsTreeStyle.offstage, |
| golden: |
| 'TestTree#00000\n' |
| ' ╎╌child node A: TestTree#00000\n' |
| ' ╎╌child node B: TestTree#00000\n' |
| ' ╎ ╎╌child node B1: TestTree#00000\n' |
| ' ╎ ╎╌child node B2: TestTree#00000\n' |
| ' ╎ └╌child node B3: TestTree#00000\n' |
| ' └╌child node C: TestTree#00000\n', |
| ); |
| |
| goldenStyleTest( |
| 'leaf children', |
| style: DiagnosticsTreeStyle.sparse, |
| lastChildStyle: DiagnosticsTreeStyle.transition, |
| golden: |
| 'TestTree#00000\n' |
| ' ├─child node A: TestTree#00000\n' |
| ' ├─child node B: TestTree#00000\n' |
| ' │ ├─child node B1: TestTree#00000\n' |
| ' │ ├─child node B2: TestTree#00000\n' |
| ' │ ╘═╦══ child node B3 ═══\n' |
| ' │ ║ TestTree#00000\n' |
| ' │ ╚═══════════\n' |
| ' ╘═╦══ child node C ═══\n' |
| ' ║ TestTree#00000\n' |
| ' ╚═══════════\n', |
| ); |
| |
| // You would never really want to make everything a leaf child like this |
| // but you can and still get a readable tree. |
| // The joint between single and double lines here is a bit clunky |
| // but we could correct that if there is any real use for this style. |
| goldenStyleTest( |
| 'leaf', |
| style: DiagnosticsTreeStyle.transition, |
| golden: |
| 'TestTree#00000:\n' |
| ' ╞═╦══ child node A ═══\n' |
| ' │ ║ TestTree#00000\n' |
| ' │ ╚═══════════\n' |
| ' ╞═╦══ child node B ═══\n' |
| ' │ ║ TestTree#00000:\n' |
| ' │ ║ ╞═╦══ child node B1 ═══\n' |
| ' │ ║ │ ║ TestTree#00000\n' |
| ' │ ║ │ ╚═══════════\n' |
| ' │ ║ ╞═╦══ child node B2 ═══\n' |
| ' │ ║ │ ║ TestTree#00000\n' |
| ' │ ║ │ ╚═══════════\n' |
| ' │ ║ ╘═╦══ child node B3 ═══\n' |
| ' │ ║ ║ TestTree#00000\n' |
| ' │ ║ ╚═══════════\n' |
| ' │ ╚═══════════\n' |
| ' ╘═╦══ child node C ═══\n' |
| ' ║ TestTree#00000\n' |
| ' ╚═══════════\n', |
| ); |
| |
| goldenStyleTest( |
| 'whitespace', |
| style: DiagnosticsTreeStyle.whitespace, |
| golden: |
| 'TestTree#00000:\n' |
| ' child node A: TestTree#00000\n' |
| ' child node B: TestTree#00000:\n' |
| ' child node B1: TestTree#00000\n' |
| ' child node B2: TestTree#00000\n' |
| ' child node B3: TestTree#00000\n' |
| ' child node C: TestTree#00000\n', |
| ); |
| |
| // Single line mode does not display children. |
| goldenStyleTest( |
| 'single line', |
| style: DiagnosticsTreeStyle.singleLine, |
| golden: 'TestTree#00000', |
| ); |
| }); |
| |
| test('TreeDiagnosticsMixin tree with properties test', () async { |
| void goldenStyleTest(String description, { |
| DiagnosticsTreeStyle style, |
| DiagnosticsTreeStyle lastChildStyle, |
| @required String golden, |
| }) { |
| final TestTree tree = TestTree( |
| properties: <DiagnosticsNode>[ |
| StringProperty('stringProperty1', 'value1', quoted: false), |
| DoubleProperty('doubleProperty1', 42.5), |
| DoubleProperty('roundedProperty', 1.0 / 3.0), |
| StringProperty('DO_NOT_SHOW', 'DO_NOT_SHOW', level: DiagnosticLevel.hidden, quoted: false), |
| DiagnosticsProperty<Object>('DO_NOT_SHOW_NULL', null, defaultValue: null), |
| DiagnosticsProperty<Object>('nullProperty', null), |
| StringProperty('node_type', '<root node>', showName: false, quoted: false), |
| ], |
| children: <TestTree>[ |
| TestTree(name: 'node A', style: style), |
| TestTree( |
| name: 'node B', |
| properties: <DiagnosticsNode>[ |
| StringProperty('p1', 'v1', quoted: false), |
| StringProperty('p2', 'v2', quoted: false), |
| ], |
| children: <TestTree>[ |
| TestTree(name: 'node B1', style: style), |
| TestTree( |
| name: 'node B2', |
| properties: <DiagnosticsNode>[StringProperty('property1', 'value1', quoted: false)], |
| style: style, |
| ), |
| TestTree( |
| name: 'node B3', |
| properties: <DiagnosticsNode>[ |
| StringProperty('node_type', '<leaf node>', showName: false, quoted: false), |
| IntProperty('foo', 42), |
| ], |
| style: lastChildStyle ?? style, |
| ), |
| ], |
| style: style, |
| ), |
| TestTree( |
| name: 'node C', |
| properties: <DiagnosticsNode>[ |
| StringProperty('foo', 'multi\nline\nvalue!', quoted: false), |
| ], |
| style: lastChildStyle ?? style, |
| ), |
| ], |
| style: lastChildStyle, |
| ); |
| |
| if (tree.style != DiagnosticsTreeStyle.singleLine) |
| expect(tree, hasAGoodToStringDeep); |
| |
| expect( |
| tree.toDiagnosticsNode(style: style).toStringDeep(), |
| equalsIgnoringHashCodes(golden), |
| reason: description, |
| ); |
| validateNodeJsonSerialization(tree.toDiagnosticsNode()); |
| } |
| |
| goldenStyleTest( |
| 'sparse', |
| style: DiagnosticsTreeStyle.sparse, |
| golden: |
| 'TestTree#00000\n' |
| ' │ stringProperty1: value1\n' |
| ' │ doubleProperty1: 42.5\n' |
| ' │ roundedProperty: 0.3\n' |
| ' │ nullProperty: null\n' |
| ' │ <root node>\n' |
| ' │\n' |
| ' ├─child node A: TestTree#00000\n' |
| ' ├─child node B: TestTree#00000\n' |
| ' │ │ p1: v1\n' |
| ' │ │ p2: v2\n' |
| ' │ │\n' |
| ' │ ├─child node B1: TestTree#00000\n' |
| ' │ ├─child node B2: TestTree#00000\n' |
| ' │ │ property1: value1\n' |
| ' │ │\n' |
| ' │ └─child node B3: TestTree#00000\n' |
| ' │ <leaf node>\n' |
| ' │ foo: 42\n' |
| ' │\n' |
| ' └─child node C: TestTree#00000\n' |
| ' foo:\n' |
| ' multi\n' |
| ' line\n' |
| ' value!\n', |
| ); |
| |
| goldenStyleTest( |
| 'dense', |
| style: DiagnosticsTreeStyle.dense, |
| golden: |
| 'TestTree#00000(stringProperty1: value1, doubleProperty1: 42.5, roundedProperty: 0.3, nullProperty: null, <root node>)\n' |
| '├child node A: TestTree#00000\n' |
| '├child node B: TestTree#00000(p1: v1, p2: v2)\n' |
| '│├child node B1: TestTree#00000\n' |
| '│├child node B2: TestTree#00000(property1: value1)\n' |
| '│└child node B3: TestTree#00000(<leaf node>, foo: 42)\n' |
| '└child node C: TestTree#00000(foo: multi\\nline\\nvalue!)\n', |
| ); |
| |
| goldenStyleTest( |
| 'dashed', |
| style: DiagnosticsTreeStyle.offstage, |
| golden: |
| 'TestTree#00000\n' |
| ' │ stringProperty1: value1\n' |
| ' │ doubleProperty1: 42.5\n' |
| ' │ roundedProperty: 0.3\n' |
| ' │ nullProperty: null\n' |
| ' │ <root node>\n' |
| ' │\n' |
| ' ╎╌child node A: TestTree#00000\n' |
| ' ╎╌child node B: TestTree#00000\n' |
| ' ╎ │ p1: v1\n' |
| ' ╎ │ p2: v2\n' |
| ' ╎ │\n' |
| ' ╎ ╎╌child node B1: TestTree#00000\n' |
| ' ╎ ╎╌child node B2: TestTree#00000\n' |
| ' ╎ ╎ property1: value1\n' |
| ' ╎ ╎\n' |
| ' ╎ └╌child node B3: TestTree#00000\n' |
| ' ╎ <leaf node>\n' |
| ' ╎ foo: 42\n' |
| ' ╎\n' |
| ' └╌child node C: TestTree#00000\n' |
| ' foo:\n' |
| ' multi\n' |
| ' line\n' |
| ' value!\n', |
| ); |
| |
| goldenStyleTest( |
| 'leaf children', |
| style: DiagnosticsTreeStyle.sparse, |
| lastChildStyle: DiagnosticsTreeStyle.transition, |
| golden: |
| 'TestTree#00000\n' |
| ' │ stringProperty1: value1\n' |
| ' │ doubleProperty1: 42.5\n' |
| ' │ roundedProperty: 0.3\n' |
| ' │ nullProperty: null\n' |
| ' │ <root node>\n' |
| ' │\n' |
| ' ├─child node A: TestTree#00000\n' |
| ' ├─child node B: TestTree#00000\n' |
| ' │ │ p1: v1\n' |
| ' │ │ p2: v2\n' |
| ' │ │\n' |
| ' │ ├─child node B1: TestTree#00000\n' |
| ' │ ├─child node B2: TestTree#00000\n' |
| ' │ │ property1: value1\n' |
| ' │ │\n' |
| ' │ ╘═╦══ child node B3 ═══\n' |
| ' │ ║ TestTree#00000:\n' |
| ' │ ║ <leaf node>\n' |
| ' │ ║ foo: 42\n' |
| ' │ ╚═══════════\n' |
| ' ╘═╦══ child node C ═══\n' |
| ' ║ TestTree#00000:\n' |
| ' ║ foo:\n' |
| ' ║ multi\n' |
| ' ║ line\n' |
| ' ║ value!\n' |
| ' ╚═══════════\n', |
| ); |
| |
| // You would never really want to make everything a transition child like |
| // this but you can and still get a readable tree. |
| goldenStyleTest( |
| 'transition', |
| style: DiagnosticsTreeStyle.transition, |
| golden: |
| 'TestTree#00000:\n' |
| ' stringProperty1: value1\n' |
| ' doubleProperty1: 42.5\n' |
| ' roundedProperty: 0.3\n' |
| ' nullProperty: null\n' |
| ' <root node>\n' |
| ' ╞═╦══ child node A ═══\n' |
| ' │ ║ TestTree#00000\n' |
| ' │ ╚═══════════\n' |
| ' ╞═╦══ child node B ═══\n' |
| ' │ ║ TestTree#00000:\n' |
| ' │ ║ p1: v1\n' |
| ' │ ║ p2: v2\n' |
| ' │ ║ ╞═╦══ child node B1 ═══\n' |
| ' │ ║ │ ║ TestTree#00000\n' |
| ' │ ║ │ ╚═══════════\n' |
| ' │ ║ ╞═╦══ child node B2 ═══\n' |
| ' │ ║ │ ║ TestTree#00000:\n' |
| ' │ ║ │ ║ property1: value1\n' |
| ' │ ║ │ ╚═══════════\n' |
| ' │ ║ ╘═╦══ child node B3 ═══\n' |
| ' │ ║ ║ TestTree#00000:\n' |
| ' │ ║ ║ <leaf node>\n' |
| ' │ ║ ║ foo: 42\n' |
| ' │ ║ ╚═══════════\n' |
| ' │ ╚═══════════\n' |
| ' ╘═╦══ child node C ═══\n' |
| ' ║ TestTree#00000:\n' |
| ' ║ foo:\n' |
| ' ║ multi\n' |
| ' ║ line\n' |
| ' ║ value!\n' |
| ' ╚═══════════\n', |
| ); |
| |
| goldenStyleTest( |
| 'whitespace', |
| style: DiagnosticsTreeStyle.whitespace, |
| golden: |
| 'TestTree#00000:\n' |
| ' stringProperty1: value1\n' |
| ' doubleProperty1: 42.5\n' |
| ' roundedProperty: 0.3\n' |
| ' nullProperty: null\n' |
| ' <root node>\n' |
| ' child node A: TestTree#00000\n' |
| ' child node B: TestTree#00000:\n' |
| ' p1: v1\n' |
| ' p2: v2\n' |
| ' child node B1: TestTree#00000\n' |
| ' child node B2: TestTree#00000:\n' |
| ' property1: value1\n' |
| ' child node B3: TestTree#00000:\n' |
| ' <leaf node>\n' |
| ' foo: 42\n' |
| ' child node C: TestTree#00000:\n' |
| ' foo:\n' |
| ' multi\n' |
| ' line\n' |
| ' value!\n', |
| ); |
| |
| // Single line mode does not display children. |
| goldenStyleTest( |
| 'single line', |
| style: DiagnosticsTreeStyle.singleLine, |
| golden: 'TestTree#00000(stringProperty1: value1, doubleProperty1: 42.5, roundedProperty: 0.3, nullProperty: null, <root node>)', |
| ); |
| |
| // There isn't anything interesting for this case as the children look the |
| // same with and without children. TODO(jacobr): this is an ugly test case. |
| // only difference is odd not clearly desirable density of B3 being right |
| // next to node C. |
| goldenStyleTest( |
| 'single line last child', |
| style: DiagnosticsTreeStyle.sparse, |
| lastChildStyle: DiagnosticsTreeStyle.singleLine, |
| golden: |
| 'TestTree#00000\n' |
| ' │ stringProperty1: value1\n' |
| ' │ doubleProperty1: 42.5\n' |
| ' │ roundedProperty: 0.3\n' |
| ' │ nullProperty: null\n' |
| ' │ <root node>\n' |
| ' │\n' |
| ' ├─child node A: TestTree#00000\n' |
| ' ├─child node B: TestTree#00000\n' |
| ' │ │ p1: v1\n' |
| ' │ │ p2: v2\n' |
| ' │ │\n' |
| ' │ ├─child node B1: TestTree#00000\n' |
| ' │ ├─child node B2: TestTree#00000\n' |
| ' │ │ property1: value1\n' |
| ' │ │\n' |
| ' │ └─child node B3: TestTree#00000(<leaf node>, foo: 42)\n' |
| ' └─child node C: TestTree#00000(foo: multi\\nline\\nvalue!)\n', |
| ); |
| }); |
| |
| test('transition test', () { |
| // Test multiple styles integrating together in the same tree due to using |
| // transition to go between styles that would otherwise be incompatible. |
| final TestTree tree = TestTree( |
| style: DiagnosticsTreeStyle.sparse, |
| properties: <DiagnosticsNode>[ |
| StringProperty('stringProperty1', 'value1'), |
| ], |
| children: <TestTree>[ |
| TestTree( |
| style: DiagnosticsTreeStyle.transition, |
| name: 'node transition', |
| properties: <DiagnosticsNode>[ |
| StringProperty('p1', 'v1'), |
| TestTree( |
| properties: <DiagnosticsNode>[ |
| DiagnosticsProperty<bool>('survived', true), |
| ], |
| ).toDiagnosticsNode(name: 'tree property', style: DiagnosticsTreeStyle.whitespace), |
| ], |
| children: <TestTree>[ |
| TestTree(name: 'dense child', style: DiagnosticsTreeStyle.dense), |
| TestTree( |
| name: 'dense', |
| properties: <DiagnosticsNode>[StringProperty('property1', 'value1')], |
| style: DiagnosticsTreeStyle.dense, |
| ), |
| TestTree( |
| name: 'node B3', |
| properties: <DiagnosticsNode>[ |
| StringProperty('node_type', '<leaf node>', showName: false, quoted: false), |
| IntProperty('foo', 42), |
| ], |
| style: DiagnosticsTreeStyle.dense |
| ), |
| ], |
| ), |
| TestTree( |
| name: 'node C', |
| properties: <DiagnosticsNode>[ |
| StringProperty('foo', 'multi\nline\nvalue!', quoted: false), |
| ], |
| style: DiagnosticsTreeStyle.sparse, |
| ), |
| ], |
| ); |
| |
| expect(tree, hasAGoodToStringDeep); |
| expect( |
| tree.toDiagnosticsNode().toStringDeep(), |
| equalsIgnoringHashCodes( |
| 'TestTree#00000\n' |
| ' │ stringProperty1: "value1"\n' |
| ' ╞═╦══ child node transition ═══\n' |
| ' │ ║ TestTree#00000:\n' |
| ' │ ║ p1: "v1"\n' |
| ' │ ║ tree property: TestTree#00000:\n' |
| ' │ ║ survived: true\n' |
| ' │ ║ ├child dense child: TestTree#00000\n' |
| ' │ ║ ├child dense: TestTree#00000(property1: "value1")\n' |
| ' │ ║ └child node B3: TestTree#00000(<leaf node>, foo: 42)\n' |
| ' │ ╚═══════════\n' |
| ' └─child node C: TestTree#00000\n' |
| ' foo:\n' |
| ' multi\n' |
| ' line\n' |
| ' value!\n', |
| ), |
| ); |
| }); |
| |
| test('describeEnum test', () { |
| expect(describeEnum(ExampleEnum.hello), equals('hello')); |
| expect(describeEnum(ExampleEnum.world), equals('world')); |
| expect(describeEnum(ExampleEnum.deferToChild), equals('deferToChild')); |
| }); |
| |
| test('string property test', () { |
| expect( |
| StringProperty('name', 'value', quoted: false).toString(), |
| equals('name: value'), |
| ); |
| |
| final StringProperty stringProperty = StringProperty( |
| 'name', |
| 'value', |
| description: 'VALUE', |
| ifEmpty: '<hidden>', |
| quoted: false, |
| ); |
| expect(stringProperty.toString(), equals('name: VALUE')); |
| validateStringPropertyJsonSerialization(stringProperty); |
| |
| expect( |
| StringProperty( |
| 'name', |
| 'value', |
| showName: false, |
| ifEmpty: '<hidden>', |
| quoted: false, |
| ).toString(), |
| equals('value'), |
| ); |
| |
| expect( |
| StringProperty('name', '', ifEmpty: '<hidden>').toString(), |
| equals('name: <hidden>'), |
| ); |
| |
| expect( |
| StringProperty( |
| 'name', |
| '', |
| ifEmpty: '<hidden>', |
| showName: false, |
| ).toString(), |
| equals('<hidden>'), |
| ); |
| |
| expect(StringProperty('name', null).isFiltered(DiagnosticLevel.info), isFalse); |
| expect(StringProperty('name', 'value', level: DiagnosticLevel.hidden).isFiltered(DiagnosticLevel.info), isTrue); |
| expect(StringProperty('name', null, defaultValue: null).isFiltered(DiagnosticLevel.info), isTrue); |
| final StringProperty quoted = StringProperty( |
| 'name', |
| 'value', |
| quoted: true, |
| ); |
| expect(quoted.toString(), equals('name: "value"')); |
| validateStringPropertyJsonSerialization(quoted); |
| |
| expect( |
| StringProperty('name', 'value', showName: false).toString(), |
| equals('"value"'), |
| ); |
| |
| expect( |
| StringProperty( |
| 'name', |
| null, |
| showName: false, |
| quoted: true, |
| ).toString(), |
| equals('null'), |
| ); |
| }); |
| |
| test('bool property test', () { |
| final DiagnosticsProperty<bool> trueProperty = DiagnosticsProperty<bool>('name', true); |
| final DiagnosticsProperty<bool> falseProperty = DiagnosticsProperty<bool>('name', false); |
| expect(trueProperty.toString(), equals('name: true')); |
| expect(trueProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(trueProperty.value, isTrue); |
| expect(falseProperty.toString(), equals('name: false')); |
| expect(falseProperty.value, isFalse); |
| expect(falseProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| validatePropertyJsonSerialization(trueProperty); |
| validatePropertyJsonSerialization(falseProperty); |
| final DiagnosticsProperty<bool> truthyProperty = DiagnosticsProperty<bool>( |
| 'name', |
| true, |
| description: 'truthy', |
| ); |
| expect( |
| truthyProperty.toString(), |
| equals('name: truthy'), |
| ); |
| validatePropertyJsonSerialization(truthyProperty); |
| expect( |
| DiagnosticsProperty<bool>('name', true, showName: false).toString(), |
| equals('true'), |
| ); |
| |
| expect(DiagnosticsProperty<bool>('name', null).isFiltered(DiagnosticLevel.info), isFalse); |
| expect(DiagnosticsProperty<bool>('name', true, level: DiagnosticLevel.hidden).isFiltered(DiagnosticLevel.info), isTrue); |
| expect(DiagnosticsProperty<bool>('name', null, defaultValue: null).isFiltered(DiagnosticLevel.info), isTrue); |
| final DiagnosticsProperty<bool> missingBool = DiagnosticsProperty<bool>('name', null, ifNull: 'missing'); |
| expect( |
| missingBool.toString(), |
| equals('name: missing'), |
| ); |
| validatePropertyJsonSerialization(missingBool); |
| }); |
| |
| test('flag property test', () { |
| final FlagProperty trueFlag = FlagProperty( |
| 'myFlag', |
| value: true, |
| ifTrue: 'myFlag', |
| ); |
| final FlagProperty falseFlag = FlagProperty( |
| 'myFlag', |
| value: false, |
| ifTrue: 'myFlag', |
| ); |
| expect(trueFlag.toString(), equals('myFlag')); |
| validateFlagPropertyJsonSerialization(trueFlag); |
| validateFlagPropertyJsonSerialization(falseFlag); |
| |
| expect(trueFlag.value, isTrue); |
| expect(falseFlag.value, isFalse); |
| |
| expect(trueFlag.isFiltered(DiagnosticLevel.fine), isFalse); |
| expect(falseFlag.isFiltered(DiagnosticLevel.fine), isTrue); |
| }); |
| |
| test('property with tooltip test', () { |
| final DiagnosticsProperty<String> withTooltip = DiagnosticsProperty<String>( |
| 'name', |
| 'value', |
| tooltip: 'tooltip', |
| ); |
| expect( |
| withTooltip.toString(), |
| equals('name: value (tooltip)'), |
| ); |
| expect(withTooltip.value, equals('value')); |
| expect(withTooltip.isFiltered(DiagnosticLevel.fine), isFalse); |
| validatePropertyJsonSerialization(withTooltip); |
| }); |
| |
| test('double property test', () { |
| final DoubleProperty doubleProperty = DoubleProperty( |
| 'name', |
| 42.0, |
| ); |
| expect(doubleProperty.toString(), equals('name: 42.0')); |
| expect(doubleProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(doubleProperty.value, equals(42.0)); |
| validateDoublePropertyJsonSerialization(doubleProperty); |
| |
| expect(DoubleProperty('name', 1.3333).toString(), equals('name: 1.3')); |
| |
| expect(DoubleProperty('name', null).toString(), equals('name: null')); |
| expect(DoubleProperty('name', null).isFiltered(DiagnosticLevel.info), equals(false)); |
| |
| expect( |
| DoubleProperty('name', null, ifNull: 'missing').toString(), |
| equals('name: missing'), |
| ); |
| |
| final DoubleProperty doubleWithUnit = DoubleProperty('name', 42.0, unit: 'px'); |
| expect(doubleWithUnit.toString(), equals('name: 42.0px')); |
| validateDoublePropertyJsonSerialization(doubleWithUnit); |
| }); |
| |
| |
| test('unsafe double property test', () { |
| final DoubleProperty safe = DoubleProperty.lazy( |
| 'name', |
| () => 42.0, |
| ); |
| expect(safe.toString(), equals('name: 42.0')); |
| expect(safe.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(safe.value, equals(42.0)); |
| validateDoublePropertyJsonSerialization(safe); |
| expect( |
| DoubleProperty.lazy('name', () => 1.3333).toString(), |
| equals('name: 1.3'), |
| ); |
| |
| expect( |
| DoubleProperty.lazy('name', () => null).toString(), |
| equals('name: null'), |
| ); |
| expect( |
| DoubleProperty.lazy('name', () => null).isFiltered(DiagnosticLevel.info), |
| equals(false), |
| ); |
| |
| final DoubleProperty throwingProperty = DoubleProperty.lazy( |
| 'name', |
| () => throw FlutterError('Invalid constraints'), |
| ); |
| // TODO(jacobr): it would be better if throwingProperty.object threw an |
| // exception. |
| expect(throwingProperty.value, isNull); |
| expect(throwingProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect( |
| throwingProperty.toString(), |
| equals('name: EXCEPTION (FlutterError)'), |
| ); |
| expect(throwingProperty.level, equals(DiagnosticLevel.error)); |
| validateDoublePropertyJsonSerialization(throwingProperty); |
| }); |
| |
| test('percent property', () { |
| expect( |
| PercentProperty('name', 0.4).toString(), |
| equals('name: 40.0%'), |
| ); |
| |
| final PercentProperty complexPercentProperty = PercentProperty('name', 0.99, unit: 'invisible', tooltip: 'almost transparent'); |
| expect( |
| complexPercentProperty.toString(), |
| equals('name: 99.0% invisible (almost transparent)'), |
| ); |
| validateDoublePropertyJsonSerialization(complexPercentProperty); |
| |
| expect( |
| PercentProperty('name', null, unit: 'invisible', tooltip: '!').toString(), |
| equals('name: null (!)'), |
| ); |
| |
| expect( |
| PercentProperty('name', 0.4).value, |
| 0.4, |
| ); |
| expect( |
| PercentProperty('name', 0.0).toString(), |
| equals('name: 0.0%'), |
| ); |
| expect( |
| PercentProperty('name', -10.0).toString(), |
| equals('name: 0.0%'), |
| ); |
| expect( |
| PercentProperty('name', 1.0).toString(), |
| equals('name: 100.0%'), |
| ); |
| expect( |
| PercentProperty('name', 3.0).toString(), |
| equals('name: 100.0%'), |
| ); |
| expect( |
| PercentProperty('name', null).toString(), |
| equals('name: null'), |
| ); |
| expect( |
| PercentProperty( |
| 'name', |
| null, |
| ifNull: 'missing', |
| ).toString(), |
| equals('name: missing'), |
| ); |
| expect( |
| PercentProperty( |
| 'name', |
| null, |
| ifNull: 'missing', |
| showName: false, |
| ).toString(), |
| equals('missing'), |
| ); |
| expect( |
| PercentProperty( |
| 'name', |
| 0.5, |
| showName: false, |
| ).toString(), |
| equals('50.0%'), |
| ); |
| }); |
| |
| test('callback property test', () { |
| final Function onClick = () {}; |
| final ObjectFlagProperty<Function> present = ObjectFlagProperty<Function>( |
| 'onClick', |
| onClick, |
| ifPresent: 'clickable', |
| ); |
| final ObjectFlagProperty<Function> missing = ObjectFlagProperty<Function>( |
| 'onClick', |
| null, |
| ifPresent: 'clickable', |
| ); |
| |
| expect(present.toString(), equals('clickable')); |
| expect(present.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(present.value, equals(onClick)); |
| validateObjectFlagPropertyJsonSerialization(present); |
| expect(missing.toString(), equals('onClick: null')); |
| expect(missing.isFiltered(DiagnosticLevel.fine), isTrue); |
| validateObjectFlagPropertyJsonSerialization(missing); |
| }); |
| |
| test('missing callback property test', () { |
| void onClick() { } |
| |
| final ObjectFlagProperty<Function> present = ObjectFlagProperty<Function>( |
| 'onClick', |
| onClick, |
| ifNull: 'disabled', |
| ); |
| final ObjectFlagProperty<Function> missing = ObjectFlagProperty<Function>( |
| 'onClick', |
| null, |
| ifNull: 'disabled', |
| ); |
| |
| expect(present.toString(), equals('onClick: Closure: () => void')); |
| expect(present.isFiltered(DiagnosticLevel.fine), isTrue); |
| expect(present.value, equals(onClick)); |
| expect(missing.toString(), equals('disabled')); |
| expect(missing.isFiltered(DiagnosticLevel.info), isFalse); |
| validateObjectFlagPropertyJsonSerialization(present); |
| validateObjectFlagPropertyJsonSerialization(missing); |
| }); |
| |
| test('describe bool property', () { |
| final FlagProperty yes = FlagProperty( |
| 'name', |
| value: true, |
| ifTrue: 'YES', |
| ifFalse: 'NO', |
| showName: true, |
| ); |
| final FlagProperty no = FlagProperty( |
| 'name', |
| value: false, |
| ifTrue: 'YES', |
| ifFalse: 'NO', |
| showName: true, |
| ); |
| expect(yes.toString(), equals('name: YES')); |
| expect(yes.level, equals(DiagnosticLevel.info)); |
| expect(yes.value, isTrue); |
| validateFlagPropertyJsonSerialization(yes); |
| expect(no.toString(), equals('name: NO')); |
| expect(no.level, equals(DiagnosticLevel.info)); |
| expect(no.value, isFalse); |
| validateFlagPropertyJsonSerialization(no); |
| |
| expect( |
| FlagProperty( |
| 'name', |
| value: true, |
| ifTrue: 'YES', |
| ifFalse: 'NO', |
| ).toString(), |
| equals('YES'), |
| ); |
| |
| expect( |
| FlagProperty( |
| 'name', |
| value: false, |
| ifTrue: 'YES', |
| ifFalse: 'NO', |
| ).toString(), |
| equals('NO'), |
| ); |
| |
| expect( |
| FlagProperty( |
| 'name', |
| value: true, |
| ifTrue: 'YES', |
| ifFalse: 'NO', |
| level: DiagnosticLevel.hidden, |
| showName: true, |
| ).level, |
| equals(DiagnosticLevel.hidden), |
| ); |
| }); |
| |
| test('enum property test', () { |
| final EnumProperty<ExampleEnum> hello = EnumProperty<ExampleEnum>( |
| 'name', |
| ExampleEnum.hello, |
| ); |
| final EnumProperty<ExampleEnum> world = EnumProperty<ExampleEnum>( |
| 'name', |
| ExampleEnum.world, |
| ); |
| final EnumProperty<ExampleEnum> deferToChild = EnumProperty<ExampleEnum>( |
| 'name', |
| ExampleEnum.deferToChild, |
| ); |
| final EnumProperty<ExampleEnum> nullEnum = EnumProperty<ExampleEnum>( |
| 'name', |
| null, |
| ); |
| expect(hello.level, equals(DiagnosticLevel.info)); |
| expect(hello.value, equals(ExampleEnum.hello)); |
| expect(hello.toString(), equals('name: hello')); |
| validatePropertyJsonSerialization(hello); |
| |
| expect(world.level, equals(DiagnosticLevel.info)); |
| expect(world.value, equals(ExampleEnum.world)); |
| expect(world.toString(), equals('name: world')); |
| validatePropertyJsonSerialization(world); |
| |
| expect(deferToChild.level, equals(DiagnosticLevel.info)); |
| expect(deferToChild.value, equals(ExampleEnum.deferToChild)); |
| expect(deferToChild.toString(), equals('name: deferToChild')); |
| validatePropertyJsonSerialization(deferToChild); |
| |
| expect(nullEnum.level, equals(DiagnosticLevel.info)); |
| expect(nullEnum.value, isNull); |
| expect(nullEnum.toString(), equals('name: null')); |
| validatePropertyJsonSerialization(nullEnum); |
| |
| final EnumProperty<ExampleEnum> matchesDefault = EnumProperty<ExampleEnum>( |
| 'name', |
| ExampleEnum.hello, |
| defaultValue: ExampleEnum.hello, |
| ); |
| expect(matchesDefault.toString(), equals('name: hello')); |
| expect(matchesDefault.value, equals(ExampleEnum.hello)); |
| expect(matchesDefault.isFiltered(DiagnosticLevel.info), isTrue); |
| validatePropertyJsonSerialization(matchesDefault); |
| |
| expect( |
| EnumProperty<ExampleEnum>( |
| 'name', |
| ExampleEnum.hello, |
| level: DiagnosticLevel.hidden, |
| ).level, |
| equals(DiagnosticLevel.hidden), |
| ); |
| }); |
| |
| test('int property test', () { |
| final IntProperty regular = IntProperty( |
| 'name', |
| 42, |
| ); |
| expect(regular.toString(), equals('name: 42')); |
| expect(regular.value, equals(42)); |
| expect(regular.level, equals(DiagnosticLevel.info)); |
| |
| final IntProperty nullValue = IntProperty( |
| 'name', |
| null, |
| ); |
| expect(nullValue.toString(), equals('name: null')); |
| expect(nullValue.value, isNull); |
| expect(nullValue.level, equals(DiagnosticLevel.info)); |
| |
| final IntProperty hideNull = IntProperty( |
| 'name', |
| null, |
| defaultValue: null, |
| ); |
| expect(hideNull.toString(), equals('name: null')); |
| expect(hideNull.value, isNull); |
| expect(hideNull.isFiltered(DiagnosticLevel.info), isTrue); |
| |
| final IntProperty nullDescription = IntProperty( |
| 'name', |
| null, |
| ifNull: 'missing', |
| ); |
| expect(nullDescription.toString(), equals('name: missing')); |
| expect(nullDescription.value, isNull); |
| expect(nullDescription.level, equals(DiagnosticLevel.info)); |
| |
| final IntProperty hideName = IntProperty( |
| 'name', |
| 42, |
| showName: false, |
| ); |
| expect(hideName.toString(), equals('42')); |
| expect(hideName.value, equals(42)); |
| expect(hideName.level, equals(DiagnosticLevel.info)); |
| |
| final IntProperty withUnit = IntProperty( |
| 'name', |
| 42, |
| unit: 'pt', |
| ); |
| expect(withUnit.toString(), equals('name: 42pt')); |
| expect(withUnit.value, equals(42)); |
| expect(withUnit.level, equals(DiagnosticLevel.info)); |
| |
| final IntProperty defaultValue = IntProperty( |
| 'name', |
| 42, |
| defaultValue: 42, |
| ); |
| expect(defaultValue.toString(), equals('name: 42')); |
| expect(defaultValue.value, equals(42)); |
| expect(defaultValue.isFiltered(DiagnosticLevel.info), isTrue); |
| |
| final IntProperty notDefaultValue = IntProperty( |
| 'name', |
| 43, |
| defaultValue: 42, |
| ); |
| expect(notDefaultValue.toString(), equals('name: 43')); |
| expect(notDefaultValue.value, equals(43)); |
| expect(notDefaultValue.level, equals(DiagnosticLevel.info)); |
| |
| final IntProperty hidden = IntProperty( |
| 'name', |
| 42, |
| level: DiagnosticLevel.hidden, |
| ); |
| expect(hidden.toString(), equals('name: 42')); |
| expect(hidden.value, equals(42)); |
| expect(hidden.level, equals(DiagnosticLevel.hidden)); |
| }); |
| |
| test('object property test', () { |
| final Rect rect = Rect.fromLTRB(0.0, 0.0, 20.0, 20.0); |
| final DiagnosticsNode simple = DiagnosticsProperty<Rect>( |
| 'name', |
| rect, |
| ); |
| expect(simple.value, equals(rect)); |
| expect(simple.level, equals(DiagnosticLevel.info)); |
| expect(simple.toString(), equals('name: Rect.fromLTRB(0.0, 0.0, 20.0, 20.0)')); |
| validatePropertyJsonSerialization(simple); |
| |
| final DiagnosticsNode withDescription = DiagnosticsProperty<Rect>( |
| 'name', |
| rect, |
| description: 'small rect', |
| ); |
| expect(withDescription.value, equals(rect)); |
| expect(withDescription.level, equals(DiagnosticLevel.info)); |
| expect(withDescription.toString(), equals('name: small rect')); |
| validatePropertyJsonSerialization(withDescription); |
| |
| final DiagnosticsProperty<Object> nullProperty = DiagnosticsProperty<Object>( |
| 'name', |
| null, |
| ); |
| expect(nullProperty.value, isNull); |
| expect(nullProperty.level, equals(DiagnosticLevel.info)); |
| expect(nullProperty.toString(), equals('name: null')); |
| validatePropertyJsonSerialization(nullProperty); |
| |
| final DiagnosticsProperty<Object> hideNullProperty = DiagnosticsProperty<Object>( |
| 'name', |
| null, |
| defaultValue: null, |
| ); |
| expect(hideNullProperty.value, isNull); |
| expect(hideNullProperty.isFiltered(DiagnosticLevel.info), isTrue); |
| expect(hideNullProperty.toString(), equals('name: null')); |
| validatePropertyJsonSerialization(hideNullProperty); |
| |
| final DiagnosticsNode nullDescription = DiagnosticsProperty<Object>( |
| 'name', |
| null, |
| ifNull: 'missing', |
| ); |
| expect(nullDescription.value, isNull); |
| expect(nullDescription.level, equals(DiagnosticLevel.info)); |
| expect(nullDescription.toString(), equals('name: missing')); |
| validatePropertyJsonSerialization(nullDescription); |
| |
| final DiagnosticsProperty<Rect> hideName = DiagnosticsProperty<Rect>( |
| 'name', |
| rect, |
| showName: false, |
| level: DiagnosticLevel.warning |
| ); |
| expect(hideName.value, equals(rect)); |
| expect(hideName.level, equals(DiagnosticLevel.warning)); |
| expect(hideName.toString(), equals('Rect.fromLTRB(0.0, 0.0, 20.0, 20.0)')); |
| validatePropertyJsonSerialization(hideName); |
| |
| final DiagnosticsProperty<Rect> hideSeparator = DiagnosticsProperty<Rect>( |
| 'Creator', |
| rect, |
| showSeparator: false, |
| ); |
| expect(hideSeparator.value, equals(rect)); |
| expect(hideSeparator.level, equals(DiagnosticLevel.info)); |
| expect( |
| hideSeparator.toString(), |
| equals('Creator Rect.fromLTRB(0.0, 0.0, 20.0, 20.0)'), |
| ); |
| validatePropertyJsonSerialization(hideSeparator); |
| }); |
| |
| test('lazy object property test', () { |
| final Rect rect = Rect.fromLTRB(0.0, 0.0, 20.0, 20.0); |
| final DiagnosticsNode simple = DiagnosticsProperty<Rect>.lazy( |
| 'name', |
| () => rect, |
| description: 'small rect', |
| ); |
| expect(simple.value, equals(rect)); |
| expect(simple.level, equals(DiagnosticLevel.info)); |
| expect(simple.toString(), equals('name: small rect')); |
| validatePropertyJsonSerialization(simple); |
| |
| final DiagnosticsProperty<Object> nullProperty = DiagnosticsProperty<Object>.lazy( |
| 'name', |
| () => null, |
| description: 'missing', |
| ); |
| expect(nullProperty.value, isNull); |
| expect(nullProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(nullProperty.toString(), equals('name: missing')); |
| validatePropertyJsonSerialization(nullProperty); |
| |
| final DiagnosticsNode hideNullProperty = DiagnosticsProperty<Object>.lazy( |
| 'name', |
| () => null, |
| description: 'missing', |
| defaultValue: null, |
| ); |
| expect(hideNullProperty.value, isNull); |
| expect(hideNullProperty.isFiltered(DiagnosticLevel.info), isTrue); |
| expect(hideNullProperty.toString(), equals('name: missing')); |
| validatePropertyJsonSerialization(hideNullProperty); |
| |
| final DiagnosticsNode hideName = DiagnosticsProperty<Rect>.lazy( |
| 'name', |
| () => rect, |
| description: 'small rect', |
| showName: false, |
| ); |
| expect(hideName.value, equals(rect)); |
| expect(hideName.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(hideName.toString(), equals('small rect')); |
| validatePropertyJsonSerialization(hideName); |
| |
| final DiagnosticsProperty<Object> throwingWithDescription = DiagnosticsProperty<Object>.lazy( |
| 'name', |
| () => throw FlutterError('Property not available'), |
| description: 'missing', |
| defaultValue: null, |
| ); |
| expect(throwingWithDescription.value, isNull); |
| expect(throwingWithDescription.exception, isFlutterError); |
| expect(throwingWithDescription.isFiltered(DiagnosticLevel.info), false); |
| expect(throwingWithDescription.toString(), equals('name: missing')); |
| validatePropertyJsonSerialization(throwingWithDescription); |
| |
| final DiagnosticsProperty<Object> throwingProperty = DiagnosticsProperty<Object>.lazy( |
| 'name', |
| () => throw FlutterError('Property not available'), |
| defaultValue: null, |
| ); |
| expect(throwingProperty.value, isNull); |
| expect(throwingProperty.exception, isFlutterError); |
| expect(throwingProperty.isFiltered(DiagnosticLevel.info), false); |
| expect(throwingProperty.toString(), equals('name: EXCEPTION (FlutterError)')); |
| validatePropertyJsonSerialization(throwingProperty); |
| }); |
| |
| test('color property test', () { |
| // Add more tests if colorProperty becomes more than a wrapper around |
| // objectProperty. |
| const Color color = Color.fromARGB(255, 255, 255, 255); |
| final DiagnosticsProperty<Color> simple = DiagnosticsProperty<Color>( |
| 'name', |
| color, |
| ); |
| validatePropertyJsonSerialization(simple); |
| expect(simple.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(simple.value, equals(color)); |
| expect(simple.propertyType, equals(Color)); |
| expect(simple.toString(), equals('name: Color(0xffffffff)')); |
| validatePropertyJsonSerialization(simple); |
| }); |
| |
| test('flag property test', () { |
| final FlagProperty show = FlagProperty( |
| 'wasLayout', |
| value: true, |
| ifTrue: 'layout computed', |
| ); |
| expect(show.name, equals('wasLayout')); |
| expect(show.value, isTrue); |
| expect(show.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(show.toString(), equals('layout computed')); |
| validateFlagPropertyJsonSerialization(show); |
| |
| final FlagProperty hide = FlagProperty( |
| 'wasLayout', |
| value: false, |
| ifTrue: 'layout computed', |
| ); |
| expect(hide.name, equals('wasLayout')); |
| expect(hide.value, isFalse); |
| expect(hide.level, equals(DiagnosticLevel.hidden)); |
| expect(hide.toString(), equals('wasLayout: false')); |
| validateFlagPropertyJsonSerialization(hide); |
| |
| final FlagProperty hideTrue = FlagProperty( |
| 'wasLayout', |
| value: true, |
| ifFalse: 'no layout computed', |
| ); |
| expect(hideTrue.name, equals('wasLayout')); |
| expect(hideTrue.value, isTrue); |
| expect(hideTrue.level, equals(DiagnosticLevel.hidden)); |
| expect(hideTrue.toString(), equals('wasLayout: true')); |
| validateFlagPropertyJsonSerialization(hideTrue); |
| }); |
| |
| test('has property test', () { |
| final Function onClick = () {}; |
| final ObjectFlagProperty<Function> has = ObjectFlagProperty<Function>.has( |
| 'onClick', |
| onClick, |
| ); |
| expect(has.name, equals('onClick')); |
| expect(has.value, equals(onClick)); |
| expect(has.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(has.toString(), equals('has onClick')); |
| validateObjectFlagPropertyJsonSerialization(has); |
| |
| final ObjectFlagProperty<Function> missing = ObjectFlagProperty<Function>.has( |
| 'onClick', |
| null, |
| ); |
| expect(missing.name, equals('onClick')); |
| expect(missing.value, isNull); |
| expect(missing.isFiltered(DiagnosticLevel.info), isTrue); |
| expect(missing.toString(), equals('onClick: null')); |
| validateObjectFlagPropertyJsonSerialization(missing); |
| }); |
| |
| test('iterable property test', () { |
| final List<int> ints = <int>[1,2,3]; |
| final IterableProperty<int> intsProperty = IterableProperty<int>( |
| 'ints', |
| ints, |
| ); |
| expect(intsProperty.value, equals(ints)); |
| expect(intsProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(intsProperty.toString(), equals('ints: 1, 2, 3')); |
| |
| final IterableProperty<Object> emptyProperty = IterableProperty<Object>( |
| 'name', |
| <Object>[], |
| ); |
| expect(emptyProperty.value, isEmpty); |
| expect(emptyProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(emptyProperty.toString(), equals('name: []')); |
| validateIterablePropertyJsonSerialization(emptyProperty); |
| |
| final IterableProperty<Object> nullProperty = IterableProperty<Object>( |
| 'list', |
| null, |
| ); |
| expect(nullProperty.value, isNull); |
| expect(nullProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect(nullProperty.toString(), equals('list: null')); |
| validateIterablePropertyJsonSerialization(nullProperty); |
| |
| final IterableProperty<Object> hideNullProperty = IterableProperty<Object>( |
| 'list', |
| null, |
| defaultValue: null, |
| ); |
| expect(hideNullProperty.value, isNull); |
| expect(hideNullProperty.isFiltered(DiagnosticLevel.info), isTrue); |
| expect(hideNullProperty.level, equals(DiagnosticLevel.fine)); |
| expect(hideNullProperty.toString(), equals('list: null')); |
| validateIterablePropertyJsonSerialization(hideNullProperty); |
| |
| final List<Object> objects = <Object>[ |
| Rect.fromLTRB(0.0, 0.0, 20.0, 20.0), |
| const Color.fromARGB(255, 255, 255, 255), |
| ]; |
| final IterableProperty<Object> objectsProperty = IterableProperty<Object>( |
| 'objects', |
| objects, |
| ); |
| expect(objectsProperty.value, equals(objects)); |
| expect(objectsProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect( |
| objectsProperty.toString(), |
| equals('objects: Rect.fromLTRB(0.0, 0.0, 20.0, 20.0), Color(0xffffffff)'), |
| ); |
| validateIterablePropertyJsonSerialization(objectsProperty); |
| |
| final IterableProperty<Object> multiLineProperty = IterableProperty<Object>( |
| 'objects', |
| objects, |
| style: DiagnosticsTreeStyle.whitespace, |
| ); |
| expect(multiLineProperty.value, equals(objects)); |
| expect(multiLineProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect( |
| multiLineProperty.toString(), |
| equals( |
| 'objects:\n' |
| 'Rect.fromLTRB(0.0, 0.0, 20.0, 20.0)\n' |
| 'Color(0xffffffff)', |
| ), |
| ); |
| expect( |
| multiLineProperty.toStringDeep(), |
| equals( |
| 'objects:\n' |
| ' Rect.fromLTRB(0.0, 0.0, 20.0, 20.0)\n' |
| ' Color(0xffffffff)\n', |
| ), |
| ); |
| validateIterablePropertyJsonSerialization(multiLineProperty); |
| |
| expect( |
| TestTree( |
| properties: <DiagnosticsNode>[multiLineProperty], |
| ).toStringDeep(), |
| equalsIgnoringHashCodes( |
| 'TestTree#00000\n' |
| ' objects:\n' |
| ' Rect.fromLTRB(0.0, 0.0, 20.0, 20.0)\n' |
| ' Color(0xffffffff)\n', |
| ), |
| ); |
| |
| expect( |
| TestTree( |
| properties: <DiagnosticsNode>[objectsProperty, IntProperty('foo', 42)], |
| style: DiagnosticsTreeStyle.singleLine, |
| ).toStringDeep(), |
| equalsIgnoringHashCodes( |
| 'TestTree#00000(objects: [Rect.fromLTRB(0.0, 0.0, 20.0, 20.0), Color(0xffffffff)], foo: 42)', |
| ), |
| ); |
| |
| // Iterable with a single entry. Verify that rendering is sensible and that |
| // multi line rendering isn't used even though it is not helpful. |
| final List<Object> singleElementList = <Object>[const Color.fromARGB(255, 255, 255, 255)]; |
| |
| final IterableProperty<Object> objectProperty = IterableProperty<Object>( |
| 'object', |
| singleElementList, |
| style: DiagnosticsTreeStyle.whitespace, |
| ); |
| expect(objectProperty.value, equals(singleElementList)); |
| expect(objectProperty.isFiltered(DiagnosticLevel.info), isFalse); |
| expect( |
| objectProperty.toString(), |
| equals('object: Color(0xffffffff)'), |
| ); |
| expect( |
| objectProperty.toStringDeep(), |
| equals('object: Color(0xffffffff)\n'), |
| ); |
| validateIterablePropertyJsonSerialization(objectProperty); |
| expect( |
| TestTree( |
| name: 'root', |
| properties: <DiagnosticsNode>[objectProperty], |
| ).toStringDeep(), |
| equalsIgnoringHashCodes( |
| 'TestTree#00000\n' |
| ' object: Color(0xffffffff)\n', |
| ), |
| ); |
| }); |
| |
| test('message test', () { |
| final DiagnosticsNode message = DiagnosticsNode.message('hello world'); |
| expect(message.toString(), equals('hello world')); |
| expect(message.name, isEmpty); |
| expect(message.value, isNull); |
| expect(message.showName, isFalse); |
| validateNodeJsonSerialization(message); |
| |
| final DiagnosticsNode messageProperty = MessageProperty('diagnostics', 'hello world'); |
| expect(messageProperty.toString(), equals('diagnostics: hello world')); |
| expect(messageProperty.name, equals('diagnostics')); |
| expect(messageProperty.value, isNull); |
| expect(messageProperty.showName, isTrue); |
| validatePropertyJsonSerialization(messageProperty); |
| }); |
| } |