/** Additional feature tests that aren't based on test data. */ library parser_feature_test; import 'package:unittest/unittest.dart'; import 'package:html5lib/dom.dart'; import 'package:html5lib/dom_parsing.dart'; import 'package:html5lib/parser.dart'; import 'package:html5lib/src/constants.dart'; import 'package:html5lib/src/tokenizer.dart'; import 'package:html5lib/src/treebuilder.dart'; main() { test('doctype is cloneable', () { var doc = parse(''); DocumentType doctype = doc.nodes[0]; expect(doctype.clone().outerHtml, ''); }); test('line counter', () { // http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0 var doc = parse("
\nx\n>\n
"); expect(doc.body.innerHtml, "
x\n>\n
"); }); test('namespace html elements on', () { var doc = new HtmlParser('', tree: new TreeBuilder(true)).parse(); expect(doc.nodes[0].namespace, Namespaces.html); }); test('namespace html elements off', () { var doc = new HtmlParser('', tree: new TreeBuilder(false)).parse(); expect(doc.nodes[0].namespace, null); }); test('parse error spans - full', () { var parser = new HtmlParser(''' ''', generateSpans: true, sourceUrl: 'ParseError'); var doc = parser.parse(); expect(doc.body.outerHtml, '\n \n \n\n'); expect(parser.errors.length, 1); ParseError error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); // Note: these values are 0-based, but the printed format is 1-based. expect(error.span.start.line, 3); expect(error.span.end.line, 3); expect(error.span.start.column, 2); expect(error.span.end.column, 17); expect(error.span.text, ''); expect(error.toString(), ''' ParseError:4:3: Unexpected DOCTYPE. Ignored. ^^^^^^^^^^^^^^^'''); }); test('parse error spans - minimal', () { var parser = new HtmlParser(''' '''); var doc = parser.parse(); expect(doc.body.outerHtml, '\n \n \n\n'); expect(parser.errors.length, 1); ParseError error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); expect(error.span.start.line, 3); // Note: error position is at the end, not the beginning expect(error.span.start.column, 17); }); test('text spans should have the correct length', () { var textContent = '\n hello {{name}}'; var html = '
$textContent
'; var doc = parse(html, generateSpans: true); var text = doc.body.nodes[0].nodes[0]; expect(text, new isInstanceOf()); expect(text.value, textContent); expect(text.sourceSpan.start.offset, html.indexOf(textContent)); expect(text.sourceSpan.length, textContent.length); }); test('attribute spans', () { var text = ''; var doc = parse(text, generateSpans: true); var elem = doc.query('element'); expect(elem.sourceSpan.start.offset, 0); expect(elem.sourceSpan.end.offset, text.length); expect(elem.sourceSpan.text, text); expect(elem.attributeSpans['quux'], null); var span = elem.attributeSpans['extends']; expect(span.start.offset, text.indexOf('extends')); expect(span.text, 'extends="x-bar"'); }); test('attribute value spans', () { var text = ''; var doc = parse(text, generateSpans: true); var elem = doc.query('element'); expect(elem.attributeValueSpans['quux'], null); var span = elem.attributeValueSpans['extends']; expect(span.start.offset, text.indexOf('x-bar')); expect(span.text, 'x-bar'); }); test('attribute spans if no attributes', () { var text = ''; var doc = parse(text, generateSpans: true); var elem = doc.query('element'); expect(elem.attributeSpans['quux'], null); expect(elem.attributeValueSpans['quux'], null); }); test('attribute spans if no attribute value', () { var text = ''; var doc = parse(text, generateSpans: true); var elem = doc.query('foo'); expect(elem.attributeSpans['template'].start.offset, text.indexOf('template')); expect(elem.attributeValueSpans.containsKey('template'), false); }); test('attribute spans null if code parsed without spans', () { var text = ''; var doc = parse(text); var elem = doc.query('element'); expect(elem.sourceSpan, null); expect(elem.attributeSpans['quux'], null); expect(elem.attributeSpans['extends'], null); }); test('void element innerHTML', () { var doc = parse('
'); expect(doc.body.innerHtml, '
'); doc = parse(''); expect(doc.body.innerHtml, ''); doc = parse('
'); expect(doc.body.innerHtml, '
'); doc = parse('
'); expect(doc.body.innerHtml, '
'); }); test('empty document has html, body, and head', () { var doc = parse(''); expect(doc.outerHtml, ''); expect(doc.head.outerHtml, ''); expect(doc.body.outerHtml, ''); }); test('strange table case', () { var doc = parseFragment(''); expect(doc.outerHtml, '
'); }); group('html serialization', () { test('attribute order', () { // Note: the spec only requires a stable order. // However, we preserve the input order via LinkedHashMap var doc = parseFragment(''); expect(doc.outerHtml, ''); expect(doc.query('foo').attributes.remove('a'), '2'); expect(doc.outerHtml, ''); doc.query('foo').attributes['a'] = '0'; expect(doc.outerHtml, ''); }); test('escaping Text node in '); expect(doc.outerHtml, ''); }); test('escaping Text node in ', () { var doc = parseFragment('a && b'); expect(doc.outerHtml, 'a && b'); }); test('Escaping attributes', () { var doc = parseFragment('
'); expect(doc.outerHtml, '
'); doc = parseFragment('
'); expect(doc.outerHtml, '
'); }); test('Escaping non-breaking space', () { var text = 'foO\u00A0bar'; expect(text.codeUnitAt(text.indexOf('O') + 1), 0xA0); var doc = parseFragment(text); expect(doc.outerHtml, 'foO bar'); }); test('Newline after
', () {
      var doc = parseFragment('
\n\nsome text');
      expect(doc.query('pre').nodes[0].value, '\nsome text');
      expect(doc.outerHtml, '
\n\nsome text
'); doc = parseFragment('
\nsome text');
      expect(doc.query('pre').nodes[0].value, 'some text');
      expect(doc.outerHtml, '
some text
'); }); test('xml namespaces', () { // Note: this is a nonsensical example, but it triggers the behavior // we're looking for with attribute names in foreign content. var doc = parse(''' '''); var n = doc.query('desc'); var keys = n.attributes.keys.toList(); expect(keys[0], new isInstanceOf()); expect(keys[0].prefix, 'xlink'); expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); expect(keys[0].name, 'type'); expect(n.outerHtml, ''); }); }); test('error printing without spans', () { var parser = new HtmlParser('foo'); var doc = parser.parse(); expect(doc.body.innerHtml, 'foo'); expect(parser.errors.length, 1); expect(parser.errors[0].errorCode, 'expected-doctype-but-got-chars'); expect(parser.errors[0].message, 'Unexpected non-space characters. Expected DOCTYPE.'); expect(parser.errors[0].toString(), 'ParserError:1:4: Unexpected non-space characters. ' 'Expected DOCTYPE.'); }); }