import 'package:petitparser/core.dart'; import 'package:petitparser/matcher.dart'; import 'package:test/test.dart'; import 'package:xml/src/xml/utils/character_data_parser.dart'; import 'package:xml/xml.dart'; void testDefaultMapping(XmlEntityMapping entityMapping) { group('decode', () { test('&#xHHHH;', () { expect(entityMapping.decode('A'), 'A'); expect(entityMapping.decode('a'), 'a'); expect(entityMapping.decode('z'), 'z'); }); test('&#dddd;', () { expect(entityMapping.decode('A'), 'A'); expect(entityMapping.decode('a'), 'a'); expect(entityMapping.decode('z'), 'z'); }); test('&named;', () { expect(entityMapping.decode('<'), '<'); expect(entityMapping.decode('>'), '>'); expect(entityMapping.decode('&'), '&'); expect(entityMapping.decode('''), '\''); expect(entityMapping.decode('"'), '"'); }); test('invalid', () { expect(entityMapping.decode('&Invalid;'), '&Invalid;'); expect(entityMapping.decode('&#Invalid;'), '&#Invalid;'); expect(entityMapping.decode('&#xInvalid;'), '&#xInvalid;'); expect(entityMapping.decode('&#XInvalid;'), '&#XInvalid;'); }); test('unicode', () { // https://www.compart.com/en/unicode/U+0000 expect(entityMapping.decode('�'), '\u0000'); expect(entityMapping.decode('�'), '\u0000'); // https://www.compart.com/en/unicode/U+10FFFF expect(entityMapping.decode('􏿿'), '\uDBFF\uDFFF'); expect(entityMapping.decode('􏿿'), '\uDBFF\uDFFF'); }); test('unicode invalid', () { expect(entityMapping.decode('&#-1;'), '&#-1;'); expect(entityMapping.decode('&#x-1;'), '&#x-1;'); expect(entityMapping.decode('�'), '�'); expect(entityMapping.decode('�'), '�'); }); test('incomplete', () { expect(entityMapping.decode('&'), '&'); expect(entityMapping.decode('&'), '&'); expect(entityMapping.decode('a&b'), 'a&b'); expect(entityMapping.decode('&>'), '&>'); }); test('empty', () { expect(entityMapping.decode('&;'), '&;'); }); test('none', () { expect(entityMapping.decode(''), ''); expect(entityMapping.decode('Hello'), 'Hello'); expect(entityMapping.decode('Hello World'), 'Hello World'); }); test('surrounded', () { expect(entityMapping.decode('a&b'), 'a&b'); expect(entityMapping.decode('&a&'), '&a&'); expect(entityMapping.decode('a&b&c'), 'a&b&c'); expect(entityMapping.decode('&a&b&'), '&a&b&'); expect(entityMapping.decode('a&b&c&d'), 'a&b&c&d'); }); test('sequence', () { expect(entityMapping.decode('&&'), '&&'); expect(entityMapping.decode('<&>'), '<&>'); }); test('document', () { final document = XmlDocument.parse( 'a&b', entityMapping: entityMapping, ); expect(document.rootElement.innerText, 'a&b'); }); test('fragment', () { final fragment = XmlDocumentFragment.parse( 'a&b', entityMapping: entityMapping, ); expect(fragment.innerText, 'a&b'); }); }); group('encode', () { test('text', () { expect(entityMapping.encodeText('<'), '<'); expect(entityMapping.encodeText('&'), '&'); expect( entityMapping.encodeText('\u0000\u0008\u0009\u0084\u0085\u0086'), '\u0000\u0009„\u0085†', ); expect(entityMapping.encodeText('hello'), 'hello'); expect(entityMapping.encodeText(''), '<foo &amp;>'); }); test('attribute (single quote)', () { expect( entityMapping.encodeAttributeValue("'", XmlAttributeType.SINGLE_QUOTE), ''', ); expect( entityMapping.encodeAttributeValue('"', XmlAttributeType.SINGLE_QUOTE), '"', ); expect( entityMapping.encodeAttributeValue('\t', XmlAttributeType.SINGLE_QUOTE), ' ', ); expect( entityMapping.encodeAttributeValue('\n', XmlAttributeType.SINGLE_QUOTE), ' ', ); expect( entityMapping.encodeAttributeValue('\r', XmlAttributeType.SINGLE_QUOTE), ' ', ); expect( entityMapping.encodeAttributeValue( '\u0000\u0008\u0009\u0084\u0085\u0086', XmlAttributeType.SINGLE_QUOTE, ), '\u0000 „\u0085†', ); expect( entityMapping.encodeAttributeValue( 'hello', XmlAttributeType.SINGLE_QUOTE, ), 'hello', ); expect( entityMapping.encodeAttributeValue( "'hello'", XmlAttributeType.SINGLE_QUOTE, ), ''hello'', ); expect( entityMapping.encodeAttributeValue( '"hello"', XmlAttributeType.SINGLE_QUOTE, ), '"hello"', ); }); test('encode attribute (double quote)', () { expect( entityMapping.encodeAttributeValue("'", XmlAttributeType.DOUBLE_QUOTE), "'", ); expect( entityMapping.encodeAttributeValue('"', XmlAttributeType.DOUBLE_QUOTE), '"', ); expect( entityMapping.encodeAttributeValue('\t', XmlAttributeType.DOUBLE_QUOTE), ' ', ); expect( entityMapping.encodeAttributeValue('\n', XmlAttributeType.DOUBLE_QUOTE), ' ', ); expect( entityMapping.encodeAttributeValue('\r', XmlAttributeType.DOUBLE_QUOTE), ' ', ); expect( entityMapping.encodeAttributeValue( '\u0000\u0008\u0009\u0084\u0085\u0086', XmlAttributeType.DOUBLE_QUOTE, ), '\u0000 „\u0085†', ); expect( entityMapping.encodeAttributeValue( 'hello', XmlAttributeType.DOUBLE_QUOTE, ), 'hello', ); expect( entityMapping.encodeAttributeValue( "'hello'", XmlAttributeType.DOUBLE_QUOTE, ), "'hello'", ); expect( entityMapping.encodeAttributeValue( '"hello"', XmlAttributeType.DOUBLE_QUOTE, ), '"hello"', ); }); }); } void main() { group('xml', () { testDefaultMapping(defaultEntityMapping); }); group('html', () { const entityMapping = XmlDefaultEntityMapping.html(); testDefaultMapping(entityMapping); test('special', () { expect(entityMapping.decode('é'), 'é'); expect(entityMapping.decode('É'), 'É'); }); }); group('html5', () { const entityMapping = XmlDefaultEntityMapping.html5(); testDefaultMapping(entityMapping); test('special', () { expect(entityMapping.decode('★'), '★'); expect(entityMapping.decode('█'), '█'); }); }); group('custom', () { const entityMapping = XmlDefaultEntityMapping({'joy': '😂', 'tears': '😢'}); test('basic', () { expect(entityMapping.decodeEntity('joy'), '😂'); expect(entityMapping.decodeEntity('tears'), '😢'); }); test('entities', () { expect(entityMapping.decode('&joy;'), '😂'); expect(entityMapping.decode('&tears;'), '😢'); }); test('document', () { final document = XmlDocument.parse( '&joy; and &tears;', entityMapping: entityMapping, ); expect(document.rootElement.innerText, '😂 and 😢'); }); test('fragment', () { final fragment = XmlDocumentFragment.parse( '&joy; and &tears;', entityMapping: entityMapping, ); expect(fragment.innerText, '😂 and 😢'); }); }); group('null', () { const entityMapping = XmlNullEntityMapping(); group('decode', () { test('basic', () { expect(entityMapping.decodeEntity(''), isNull); expect(entityMapping.decodeEntity('amp'), isNull); expect(entityMapping.decodeEntity('#X41'), isNull); expect(entityMapping.decodeEntity('#65'), isNull); }); test('entities', () { expect(entityMapping.decode('A'), 'A'); expect(entityMapping.decode('A'), 'A'); expect(entityMapping.decode('&'), '&'); }); test('invalid entities', () { expect(entityMapping.decode('&;'), '&;'); expect(entityMapping.decode('&invalid;'), '&invalid;'); expect(entityMapping.decode('&incomplete'), '&incomplete'); }); test('combinations', () { expect(entityMapping.decode('a&b'), 'a&b'); expect(entityMapping.decode('&x&'), '&x&'); expect(entityMapping.decode('&&'), '&&'); }); }); group('encode', () { test('text', () { expect(entityMapping.encodeText('<'), '<'); expect(entityMapping.encodeText('&'), '&'); expect(entityMapping.encodeText('hello'), 'hello'); expect(entityMapping.encodeText(''), ''); }); test('attribute', () { expect( entityMapping.encodeAttributeValue( '<>&\'"', XmlAttributeType.SINGLE_QUOTE, ), '<>&\'"', ); expect( entityMapping.encodeAttributeValue( '<>&\'"', XmlAttributeType.DOUBLE_QUOTE, ), '<>&\'"', ); }); }); }); group('character parser', () { final parser = XmlCharacterDataParser('*', 1); test('parse without stopper', () { final result1 = parser.parse(''); expect(result1 is Failure, isTrue); expect(result1.position, 0); final result2 = parser.parse('a'); expect(result2 is Success, isTrue); expect(result2.position, 1); expect(result2.value, 'a'); final result3 = parser.parse('ab'); expect(result3 is Success, isTrue); expect(result3.position, 2); expect(result3.value, 'ab'); }); test('parse with stopper', () { final result1 = parser.parse('*'); expect(result1 is Failure, isTrue); expect(result1.position, 0); final result2 = parser.parse('a*'); expect(result2 is Success, isTrue); expect(result2.position, 1); expect(result2.value, 'a'); final result3 = parser.parse('ab*'); expect(result3 is Success, isTrue); expect(result3.position, 2); expect(result3.value, 'ab'); }); test('fast parse without stopper', () { expect(parser.accept(''), isFalse); expect(parser.accept('a'), isTrue); expect(parser.accept('ab'), isTrue); }); test('fast parse with stopper', () { expect(parser.accept('*'), isFalse); expect(parser.accept('a*'), isTrue); expect(parser.accept('ab*'), isTrue); }); test('copy and equality', () { expect(parser.isEqualTo(parser), isTrue); expect(parser.isEqualTo(parser.copy()), isTrue); expect(parser.isEqualTo(XmlCharacterDataParser('%', 1)), isFalse); expect(parser.isEqualTo(XmlCharacterDataParser('*', 2)), isFalse); }); }); }