// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; import 'package:yaml_edit/src/utils.dart'; import 'package:yaml_edit/yaml_edit.dart'; import 'test_utils.dart'; void main() { group('indentation', () { test('returns 2 for empty strings', () { final doc = YamlEditor(''); expect(getIndentation(doc), equals(2)); }); test('returns 2 for strings consisting only scalars', () { final doc = YamlEditor('foo'); expect(getIndentation(doc), equals(2)); }); test('returns 2 if only top-level elements are present', () { final doc = YamlEditor(''' - 1 - 2 - 3'''); expect(getIndentation(doc), equals(2)); }); test('detects the indentation used in nested list', () { final doc = YamlEditor(''' - 1 - 2 - - 3 - 4'''); expect(getIndentation(doc), equals(3)); }); test('detects the indentation used in nested map', () { final doc = YamlEditor(''' a: 1 b: 2 c: d: 4 e: 5'''); expect(getIndentation(doc), equals(3)); }); test('detects the indentation used in nested map in list', () { final doc = YamlEditor(''' - 1 - 2 - d: 4 e: 5'''); expect(getIndentation(doc), equals(4)); }); test('detects the indentation used in nested map in list with complex keys', () { final doc = YamlEditor(''' - 1 - 2 - ? d : 4'''); expect(getIndentation(doc), equals(4)); }); test('detects the indentation used in nested list in map', () { final doc = YamlEditor(''' a: 1 b: 2 c: - 4 - 5'''); expect(getIndentation(doc), equals(2)); }); }); group('styling options', () { group('update', () { test('flow map with style', () { final doc = YamlEditor("{YAML: YAML Ain't Markup Language}"); doc.update(['YAML'], wrapAsYamlNode('hi', scalarStyle: ScalarStyle.DOUBLE_QUOTED)); expect(doc.toString(), equals('{YAML: "hi"}')); expectYamlBuilderValue(doc, {'YAML': 'hi'}); }); test('prevents block scalars in flow map', () { final doc = YamlEditor("{YAML: YAML Ain't Markup Language}"); doc.update( ['YAML'], wrapAsYamlNode('test', scalarStyle: ScalarStyle.FOLDED)); expect(doc.toString(), equals('{YAML: test}')); expectYamlBuilderValue(doc, {'YAML': 'test'}); }); test('wraps string in double-quotes if it contains dangerous characters', () { final doc = YamlEditor("{YAML: YAML Ain't Markup Language}"); doc.update( ['YAML'], wrapAsYamlNode('> test', scalarStyle: ScalarStyle.PLAIN)); expect(doc.toString(), equals('{YAML: "> test"}')); expectYamlBuilderValue(doc, {'YAML': '> test'}); }); test('list in map', () { final doc = YamlEditor('''YAML: YAML Ain't Markup Language'''); doc.update(['YAML'], wrapAsYamlNode([1, 2, 3], collectionStyle: CollectionStyle.FLOW)); expect(doc.toString(), equals('YAML: [1, 2, 3]')); expectYamlBuilderValue(doc, { 'YAML': [1, 2, 3] }); }); test('nested map', () { final doc = YamlEditor('''YAML: YAML Ain't Markup Language'''); doc.update( ['YAML'], wrapAsYamlNode({'YAML': "YAML Ain't Markup Language"}, collectionStyle: CollectionStyle.FLOW)); expect( doc.toString(), equals("YAML: {YAML: YAML Ain't Markup Language}")); expectYamlBuilderValue(doc, { 'YAML': {'YAML': "YAML Ain't Markup Language"} }); }); test('nested list', () { final doc = YamlEditor('- 0'); doc.update( [0], wrapAsYamlNode([ 1, 2, wrapAsYamlNode([3, 4], collectionStyle: CollectionStyle.FLOW), 5 ])); expect(doc.toString(), equals(''' - - 1 - 2 - [3, 4] - 5''')); expectYamlBuilderValue(doc, [ [ 1, 2, [3, 4], 5 ] ]); }); test('different scalars in block list!', () { final doc = YamlEditor('- 0'); doc.update( [0], wrapAsYamlNode([ wrapAsYamlNode('plain string', scalarStyle: ScalarStyle.PLAIN), wrapAsYamlNode('folded string', scalarStyle: ScalarStyle.FOLDED), wrapAsYamlNode('single-quoted string', scalarStyle: ScalarStyle.SINGLE_QUOTED), wrapAsYamlNode('literal string', scalarStyle: ScalarStyle.LITERAL), wrapAsYamlNode('double-quoted string', scalarStyle: ScalarStyle.DOUBLE_QUOTED), ])); expect(doc.toString(), equals(''' - - plain string - >- folded string - 'single-quoted string' - |- literal string - "double-quoted string"''')); expectYamlBuilderValue(doc, [ [ 'plain string', 'folded string', 'single-quoted string', 'literal string', 'double-quoted string', ] ]); }); test('different scalars in block map!', () { final doc = YamlEditor('strings: strings'); doc.update( ['strings'], wrapAsYamlNode({ 'plain': wrapAsYamlNode('string', scalarStyle: ScalarStyle.PLAIN), 'folded': wrapAsYamlNode('string', scalarStyle: ScalarStyle.FOLDED), 'single-quoted': wrapAsYamlNode('string', scalarStyle: ScalarStyle.SINGLE_QUOTED), 'literal': wrapAsYamlNode('string', scalarStyle: ScalarStyle.LITERAL), 'double-quoted': wrapAsYamlNode('string', scalarStyle: ScalarStyle.DOUBLE_QUOTED), })); expect(doc.toString(), equals(''' strings: plain: string folded: >- string single-quoted: 'string' literal: |- string double-quoted: "string"''')); expectYamlBuilderValue(doc, { 'strings': { 'plain': 'string', 'folded': 'string', 'single-quoted': 'string', 'literal': 'string', 'double-quoted': 'string', } }); }); test('different scalars in flow list!', () { final doc = YamlEditor('[0]'); doc.update( [0], wrapAsYamlNode([ wrapAsYamlNode('plain string', scalarStyle: ScalarStyle.PLAIN), wrapAsYamlNode('folded string', scalarStyle: ScalarStyle.FOLDED), wrapAsYamlNode('single-quoted string', scalarStyle: ScalarStyle.SINGLE_QUOTED), wrapAsYamlNode('literal string', scalarStyle: ScalarStyle.LITERAL), wrapAsYamlNode('double-quoted string', scalarStyle: ScalarStyle.DOUBLE_QUOTED), ])); expect( doc.toString(), equals( '[[plain string, folded string, \'single-quoted string\', ' 'literal string, "double-quoted string"]]', ), ); expectYamlBuilderValue(doc, [ [ 'plain string', 'folded string', 'single-quoted string', 'literal string', 'double-quoted string', ] ]); }); test('wraps non-printable strings in double-quotes in flow context', () { final doc = YamlEditor('[0]'); doc.update([0], '\x00\x07\x08\x0b\x0c\x0d\x1b\x85\xa0\u2028\u2029"'); expect( doc.toString(), equals('["\\0\\a\\b\\v\\f\\r\\e\\N\\_\\L\\P\\""]')); expectYamlBuilderValue( doc, ['\x00\x07\x08\x0b\x0c\x0d\x1b\x85\xa0\u2028\u2029"']); }); test('wraps non-printable strings in double-quotes in block context', () { final doc = YamlEditor('- 0'); doc.update([0], '\x00\x07\x08\x0b\x0c\x0d\x1b\x85\xa0\u2028\u2029"'); expect( doc.toString(), equals('- "\\0\\a\\b\\v\\f\\r\\e\\N\\_\\L\\P\\""')); expectYamlBuilderValue( doc, ['\x00\x07\x08\x0b\x0c\x0d\x1b\x85\xa0\u2028\u2029"']); }); test('generates folded strings properly', () { final doc = YamlEditor(''); doc.update( [], wrapAsYamlNode('test\ntest', scalarStyle: ScalarStyle.FOLDED)); expect(doc.toString(), equals('>-\n test\n\n test')); }); test('rewrites folded strings properly', () { final doc = YamlEditor(''' - > folded string '''); doc.update( [0], wrapAsYamlNode('test\ntest', scalarStyle: ScalarStyle.FOLDED)); expect(doc.toString(), equals(''' - >- test test ''')); }); test('rewrites folded strings properly (1)', () { final doc = YamlEditor(''' - > folded string'''); doc.update( [0], wrapAsYamlNode('test\ntest', scalarStyle: ScalarStyle.FOLDED)); expect(doc.toString(), equals(''' - >- test test''')); }); test('generates literal strings properly', () { final doc = YamlEditor(''); doc.update( [], wrapAsYamlNode('test\ntest', scalarStyle: ScalarStyle.LITERAL)); expect(doc.toString(), equals('|-\n test\n test')); }); test('rewrites literal strings properly', () { final doc = YamlEditor(''' - | literal string '''); doc.update([0], wrapAsYamlNode('test\ntest', scalarStyle: ScalarStyle.LITERAL)); expect(doc.toString(), equals(''' - |- test test ''')); }); test('prevents literal strings in flow maps, even if nested', () { final doc = YamlEditor(''' {1: 1} '''); doc.update([ 1 ], [ wrapAsYamlNode('d9]zH`FoYC/>]', scalarStyle: ScalarStyle.LITERAL) ]); expect(doc.toString(), equals(''' {1: ["d9]zH`FoYC\\/>]"]} ''')); expect((doc.parseAt([1, 0]) as YamlScalar).style, equals(ScalarStyle.DOUBLE_QUOTED)); }); test('prevents literal empty strings', () { final doc = YamlEditor(''' a: c: 1 '''); doc.update([ 'a' ], { 'f': wrapAsYamlNode('', scalarStyle: ScalarStyle.LITERAL), 'g': 1 }); expect(doc.toString(), equals(''' a: f: "" g: 1 ''')); }); test('prevents literal strings with leading spaces', () { final doc = YamlEditor(''' a: c: 1 '''); doc.update([ 'a' ], { 'f': wrapAsYamlNode(' a', scalarStyle: ScalarStyle.LITERAL), 'g': 1 }); expect(doc.toString(), equals(''' a: f: " a" g: 1 ''')); }); test( 'flow collection structure does not get substringed when added to ' 'block structure', () { final doc = YamlEditor(''' a: - false '''); doc.prependToList(['a'], wrapAsYamlNode([1234], collectionStyle: CollectionStyle.FLOW)); expect(doc.toString(), equals(''' a: - [1234] - false ''')); expectYamlBuilderValue(doc, { 'a': [ [1234], false ] }); }); }); }); group('assertValidScalar', () { test('does nothing with a boolean', () { expect(() => assertValidScalar(true), returnsNormally); }); test('does nothing with a number', () { expect(() => assertValidScalar(1.12), returnsNormally); }); test('does nothing with infinity', () { expect(() => assertValidScalar(double.infinity), returnsNormally); }); test('does nothing with a String', () { expect(() => assertValidScalar('test'), returnsNormally); }); test('does nothing with null', () { expect(() => assertValidScalar(null), returnsNormally); }); test('throws on map', () { expect(() => assertValidScalar({'a': 1}), throwsArgumentError); }); test('throws on list', () { expect(() => assertValidScalar([1]), throwsArgumentError); }); }); }