| Index: packages/html/test/support.dart
|
| diff --git a/packages/html/test/support.dart b/packages/html/test/support.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1b4c0b49e50b57ba4216d55a0cc535ba5b2da7d2
|
| --- /dev/null
|
| +++ b/packages/html/test/support.dart
|
| @@ -0,0 +1,164 @@
|
| +/// Support code for the tests in this directory.
|
| +library support;
|
| +
|
| +import 'dart:io';
|
| +import 'dart:collection';
|
| +import 'package:path/path.dart' as path;
|
| +import 'package:html/src/treebuilder.dart';
|
| +import 'package:html/dom.dart';
|
| +import 'package:html/dom_parsing.dart';
|
| +
|
| +typedef TreeBuilder TreeBuilderFactory(bool namespaceHTMLElements);
|
| +
|
| +Map _treeTypes;
|
| +Map<String, TreeBuilderFactory> get treeTypes {
|
| + if (_treeTypes == null) {
|
| + // TODO(jmesserly): add DOM here once it's implemented
|
| + _treeTypes = {"simpletree": (useNs) => new TreeBuilder(useNs)};
|
| + }
|
| + return _treeTypes;
|
| +}
|
| +
|
| +final testDataDir = Platform.script.resolve('data').toFilePath();
|
| +
|
| +Iterable<String> getDataFiles(String subdirectory) {
|
| + var dir = new Directory(path.join(testDataDir, subdirectory));
|
| + return dir.listSync().where((f) => f is File).map((f) => f.path);
|
| +}
|
| +
|
| +// TODO(jmesserly): make this class simpler. We could probably split on
|
| +// "\n#" instead of newline and remove a lot of code.
|
| +class TestData extends IterableBase<Map> {
|
| + final String _text;
|
| + final String newTestHeading;
|
| +
|
| + TestData(String filename, [this.newTestHeading = "data"])
|
| + // Note: can't use readAsLinesSync here because it splits on \r
|
| + : _text = new File(filename).readAsStringSync();
|
| +
|
| + // Note: in Python this was a generator, but since we can't do that in Dart,
|
| + // it's easier to convert it into an upfront computation.
|
| + Iterator<Map> get iterator => _getData().iterator;
|
| +
|
| + List<Map> _getData() {
|
| + var data = <String, String>{};
|
| + var key = null;
|
| + var result = <Map>[];
|
| + var lines = _text.split('\n');
|
| + // Remove trailing newline to match Python
|
| + if (lines.last == '') {
|
| + lines.removeLast();
|
| + }
|
| + for (var line in lines) {
|
| + var heading = sectionHeading(line);
|
| + if (heading != null) {
|
| + if (data.length > 0 && heading == newTestHeading) {
|
| + // Remove trailing newline
|
| + data[key] = data[key].substring(0, data[key].length - 1);
|
| + result.add(normaliseOutput(data));
|
| + data = <String, String>{};
|
| + }
|
| + key = heading;
|
| + data[key] = "";
|
| + } else if (key != null) {
|
| + data[key] = '${data[key]}$line\n';
|
| + }
|
| + }
|
| +
|
| + if (data.length > 0) {
|
| + result.add(normaliseOutput(data));
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + /// If the current heading is a test section heading return the heading,
|
| + /// otherwise return null.
|
| + static String sectionHeading(String line) {
|
| + return line.startsWith("#") ? line.substring(1).trim() : null;
|
| + }
|
| +
|
| + static Map normaliseOutput(Map data) {
|
| + // Remove trailing newlines
|
| + data.forEach((key, value) {
|
| + if (value.endsWith("\n")) {
|
| + data[key] = value.substring(0, value.length - 1);
|
| + }
|
| + });
|
| + return data;
|
| + }
|
| +}
|
| +
|
| +/// Serialize the [document] into the html5 test data format.
|
| +testSerializer(document) {
|
| + return (new TestSerializer()..visit(document)).toString();
|
| +}
|
| +
|
| +/// Serializes the DOM into test format. See [testSerializer].
|
| +class TestSerializer extends TreeVisitor {
|
| + final StringBuffer _str;
|
| + int _indent = 0;
|
| + String _spaces = '';
|
| +
|
| + TestSerializer() : _str = new StringBuffer();
|
| +
|
| + String toString() => _str.toString();
|
| +
|
| + int get indent => _indent;
|
| +
|
| + set indent(int value) {
|
| + if (_indent == value) return;
|
| +
|
| + var arr = new List<int>(value);
|
| + for (int i = 0; i < value; i++) {
|
| + arr[i] = 32;
|
| + }
|
| + _spaces = new String.fromCharCodes(arr);
|
| + _indent = value;
|
| + }
|
| +
|
| + void _newline() {
|
| + if (_str.length > 0) _str.write('\n');
|
| + _str.write('|$_spaces');
|
| + }
|
| +
|
| + visitNodeFallback(Node node) {
|
| + _newline();
|
| + _str.write(node);
|
| + visitChildren(node);
|
| + }
|
| +
|
| + visitChildren(Node node) {
|
| + indent += 2;
|
| + for (var child in node.nodes) visit(child);
|
| + indent -= 2;
|
| + }
|
| +
|
| + visitDocument(node) {
|
| + indent += 1;
|
| + for (var child in node.nodes) visit(child);
|
| + indent -= 1;
|
| + }
|
| +
|
| + visitDocumentFragment(DocumentFragment node) => visitDocument(node);
|
| +
|
| + visitElement(Element node) {
|
| + _newline();
|
| + _str.write(node);
|
| + if (node.attributes.length > 0) {
|
| + indent += 2;
|
| + var keys = new List.from(node.attributes.keys);
|
| + keys.sort((x, y) => x.compareTo(y));
|
| + for (var key in keys) {
|
| + var v = node.attributes[key];
|
| + if (key is AttributeName) {
|
| + AttributeName attr = key;
|
| + key = "${attr.prefix} ${attr.name}";
|
| + }
|
| + _newline();
|
| + _str.write('$key="$v"');
|
| + }
|
| + indent -= 2;
|
| + }
|
| + visitChildren(node);
|
| + }
|
| +}
|
|
|