Skip to main content
Module

std/toml/parse_test.ts

The Deno Standard Library
Latest
File
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.import { assertEquals, assertThrows } from "../assert/mod.ts";import { ArrayValue, BareKey, BasicString, DateTime, DottedKey, Float, InlineTable, Integer, LiteralString, LocalTime, MultilineBasicString, MultilineLiteralString, Pair, ParserFactory, Scanner, Symbols, Table, TOMLParseError, Utils, Value,} from "./_parser.ts";import { parse, stringify } from "./mod.ts";import { existsSync } from "../fs/exists.ts";import * as path from "../path/mod.ts";
const moduleDir = path.dirname(path.fromFileUrl(import.meta.url));const testdataDir = path.resolve(moduleDir, "./testdata");
function parseFile(filePath: string): Record<string, unknown> { if (!existsSync(filePath)) { throw new Error(`File not found: ${filePath}`); } return parse(Deno.readTextFileSync(filePath));}
Deno.test({ name: "Scanner", fn() { const scanner = new Scanner(" # comment\n\n\na \nb"); scanner.nextUntilChar({ inline: true }); assertEquals(scanner.char(), "#"); scanner.nextUntilChar(); assertEquals(scanner.char(), "a"); scanner.next(); scanner.nextUntilChar({ inline: true }); assertEquals(scanner.char(), "\n"); scanner.nextUntilChar(); assertEquals(scanner.char(), "b"); scanner.next(); assertEquals(scanner.eof(), true); },});
Deno.test({ name: "parse() handles bare key", fn() { const parse = ParserFactory(BareKey); assertEquals(parse("A-Za-z0-9_-"), "A-Za-z0-9_-"); assertThrows(() => parse("")); assertThrows(() => parse('"foo"')); },});
Deno.test({ name: "parse() handles basic string", fn() { const parse = ParserFactory(BasicString); assertEquals( parse('"a\\"\\n\\t\\b\\\\\\u3042\\U01F995"'), 'a"\n\t\b\\\あ🦕', ); assertEquals(parse('""'), ""); assertEquals(parse('"a\\n"'), "a\n"); assertThrows( () => parse('"a\\0b\\?c"'), TOMLParseError, "Invalid escape sequence: \\0", ); assertThrows(() => parse("")); assertThrows(() => parse('"a')); assertThrows(() => parse('"a\nb"')); },});
Deno.test({ name: "parse() handles literal string", fn() { const parse = ParserFactory(LiteralString); assertEquals(parse("'a\\n'"), "a\\n"); assertThrows(() => parse("")); assertThrows(() => parse("'a")); assertThrows(() => parse("a\nb")); },});
Deno.test({ name: "parse() handles multi-line basic string", fn() { const parse = ParserFactory(MultilineBasicString); assertEquals( parse(`"""Roses are redViolets are\\tblue"""`), "Roses are red\nViolets are\tblue", ); assertEquals( parse(`"""\\ The quick brown \\ fox jumps over \\ the lazy dog.\\ """`), "The quick brown fox jumps over the lazy dog.", ); assertThrows( () => parse(`"""\\ The quick brown \\ fox jumps over\\? \\ the lazy dog\\0.\\ """`), TOMLParseError, "Invalid escape sequence: \\?", ); assertThrows( () => parse(`"""Roses are redViolets are\\tblue`), TOMLParseError, "not closed", ); },});
Deno.test({ name: "parse() handles multi-line basic string (CRLF)", fn() { const parse = ParserFactory(MultilineBasicString); assertEquals( parse(`"""\rRoses are red\rViolets are\\tblue"""`), "Roses are red\r\nViolets are\tblue", ); assertEquals( parse(`"""\\\r The quick brown \\\r fox jumps over \\\r the lazy dog.\\\r """`), "The quick brown fox jumps over the lazy dog.", ); },});
Deno.test({ name: "parse() handles multi-line literal string", fn() { const parse = ParserFactory(MultilineLiteralString); assertEquals( parse(`'''Roses are redViolets are\\tblue'''`), "Roses are red\nViolets are\\tblue", ); assertThrows( () => parse(`'''Roses are redViolets are\\tblue`), TOMLParseError, "not closed", ); },});
Deno.test({ name: "parse() handles multi-line literal string (CRLF)", fn() { const parse = ParserFactory(MultilineLiteralString); assertEquals( parse(`'''\rRoses are red\rViolets are\\tblue'''`), "Roses are red\r\nViolets are\\tblue", ); },});
Deno.test({ name: "parse() handles symbols", fn() { const parse = ParserFactory(Symbols); assertEquals(parse("true"), true); assertEquals(parse("nan"), NaN); assertEquals(parse("inf"), Infinity); assertThrows(() => parse("")); assertThrows(() => parse("_")); },});
Deno.test({ name: "parse() handles dotted key", fn() { const parse = ParserFactory(DottedKey); assertEquals(parse("a . b . c"), ["a", "b", "c"]); assertEquals(parse(`a.'b.c'."d.e"`), ["a", "b.c", "d.e"]); assertThrows(() => parse("")); assertThrows(() => parse("a.b .")); assertThrows(() => parse(".")); },});
Deno.test({ name: "parse() handles table", fn() { const parse = ParserFactory(Table); assertEquals( parse(`[foo.bar]baz = truefizz.buzz = true`.trim()), { type: "Table", key: ["foo", "bar"], value: { baz: true, fizz: { buzz: true, }, }, }, ); assertEquals(parse(`[only.header]`), { type: "Table", key: ["only", "header"], value: {}, }); assertThrows(() => parse("")); assertThrows(() => parse("[")); assertThrows(() => parse("[o")); },});
Deno.test({ name: "parse() handles integer", fn() { const parse = ParserFactory(Integer); assertEquals(parse("123"), 123); assertEquals(parse("+123"), 123); assertEquals(parse("-123"), -123); assertEquals(parse("123_456"), 123456); assertEquals(parse("0xDEADBEEF"), "0xDEADBEEF"); assertEquals(parse("0xdeadbeef"), "0xdeadbeef"); assertEquals(parse("0xdead_beef"), "0xdead_beef"); assertEquals(parse("0o01234567"), "0o01234567"); assertEquals(parse("0o755"), "0o755"); assertEquals(parse("0b11010110"), "0b11010110"); assertThrows(() => parse("")); assertThrows(() => parse("+Z")); assertThrows(() => parse("0x")); },});
Deno.test({ name: "parse() handles float", fn() { const parse = ParserFactory(Float); assertEquals(parse("+1.0"), 1.0); assertEquals(parse("3.1415"), 3.1415); assertEquals(parse("-0.01"), -0.01); assertEquals(parse("5e+22"), 5e+22); assertEquals(parse("1e06"), 1e06); assertEquals(parse("-2E-2"), -2E-2); assertEquals(parse("6.626e-34"), 6.626e-34); assertEquals(parse("224_617.445_991_228"), 224_617.445_991_228); assertThrows(() => parse("")); assertThrows(() => parse("X")); assertThrows(() => parse("e_+-")); },});
Deno.test({ name: "parse() handles date and date time", fn() { const parse = ParserFactory(DateTime); assertEquals( parse("1979-05-27T07:32:00Z"), new Date("1979-05-27T07:32:00Z"), ); assertEquals( parse("1979-05-27T00:32:00-07:00"), new Date("1979-05-27T07:32:00Z"), ); assertEquals( parse("1979-05-27T00:32:00.999999-07:00"), new Date("1979-05-27T07:32:00.999Z"), ); assertEquals( parse("1979-05-27 07:32:00Z"), new Date("1979-05-27T07:32:00Z"), ); assertEquals(parse("1979-05-27T07:32:00"), new Date("1979-05-27T07:32:00")); assertEquals( parse("1979-05-27T00:32:00.999999"), new Date("1979-05-27T00:32:00.999999"), ); assertEquals(parse("1979-05-27"), new Date("1979-05-27")); assertThrows(() => parse("")); assertThrows(() => parse("X")); assertThrows(() => parse("0000-00-00")); },});
Deno.test({ name: "parse() handles local time", fn() { const parse = ParserFactory(LocalTime); assertEquals(parse("07:32:00"), "07:32:00"); assertEquals(parse("07:32:00.999"), "07:32:00.999"); assertThrows(() => parse("")); },});
Deno.test({ name: "parse() handles value", fn() { const parse = ParserFactory(Value); assertEquals(parse("1"), 1); assertEquals(parse("1.2"), 1.2); assertEquals(parse("1979-05-27"), new Date("1979-05-27")); assertEquals(parse("07:32:00"), "07:32:00"); assertEquals(parse(`"foo.com"`), "foo.com"); assertEquals(parse(`'foo.com'`), "foo.com"); },});
Deno.test({ name: "parse() handles key value pair", fn() { const parse = ParserFactory(Pair); assertEquals(parse("key = 'value'"), { key: "value" }); assertThrows(() => parse("key =")); assertThrows(() => parse("key = \n 'value'")); assertThrows(() => parse("key \n = 'value'")); },});
Deno.test({ name: "parse() handles array", fn() { const parse = ParserFactory(ArrayValue); assertEquals(parse("[]"), []); assertEquals(parse("[1, 2, 3]"), [1, 2, 3]); assertEquals(parse(`[ "red", "yellow", "green" ]`), [ "red", "yellow", "green", ]); assertEquals(parse(`[ [ 1, 2 ], [3, 4, 5] ]`), [[1, 2], [3, 4, 5]]); assertEquals(parse(`[ [ 1, 2 ], ["a", "b", "c"] ]`), [ [1, 2], ["a", "b", "c"], ]); assertEquals( parse(`[ { x = 1, y = 2, z = 3 }, { x = 7, y = 8, z = 9 }, { x = 2, y = 4, z = 8 } ]`), [{ x: 1, y: 2, z: 3 }, { x: 7, y: 8, z: 9 }, { x: 2, y: 4, z: 8 }], ); assertEquals( parse(`[ # comment 1, # comment 2, # this is ok ]`), [1, 2], ); assertThrows(() => parse("[1, 2, 3"), TOMLParseError, "not closed"); },});
Deno.test({ name: "parse() handles inline table", fn() { const parse = ParserFactory(InlineTable); assertEquals(parse(`{ first = "Tom", last = "Preston-Werner" }`), { first: "Tom", last: "Preston-Werner", }); assertEquals(parse(`{ type.name = "pug" }`), { type: { name: "pug" } }); assertThrows(() => parse(`{ x = 1`)); assertThrows(() => parse(`{ x = 1,\n y = 2 }`)); assertThrows(() => parse(`{ x = 1, }`)); },});
Deno.test({ name: "parse() handles Utils.deepAssignWithTable", fn() { const source = { foo: { items: [ { id: "a", }, { id: "b", profile: { name: "b", }, }, ], }, };
Utils.deepAssignWithTable( source, { type: "Table", key: ["foo", "items", "profile", "email", "x"], value: { main: "mail@example.com" }, }, ); assertEquals( source, { foo: { items: [ { id: "a", }, { id: "b", profile: { name: "b", email: { x: { main: "mail@example.com" }, }, } as unknown, }, ], }, }, ); },});
Deno.test({ name: "parse() handles Utils.deepAssignWithTable / TableArray", fn() { const source = { foo: {}, bar: null, };
Utils.deepAssignWithTable( source, { type: "TableArray", key: ["foo", "items"], value: { email: "mail@example.com" }, }, ); assertEquals( source, { foo: { items: [ { email: "mail@example.com", }, ], }, bar: null, }, ); Utils.deepAssignWithTable( source, { type: "TableArray", key: ["foo", "items"], value: { email: "sub@example.com" }, }, ); assertEquals( source, { foo: { items: [ { email: "mail@example.com", }, { email: "sub@example.com", }, ], }, bar: null, }, );
assertThrows( () => Utils.deepAssignWithTable( source, { type: "TableArray", key: [], value: { email: "sub@example.com" }, }, ), Error, "Unexpected key length", );
assertThrows( () => Utils.deepAssignWithTable( source, { type: "TableArray", key: ["bar", "items"], value: { email: "mail@example.com" }, }, ), Error, "Unexpected assign", ); },});
Deno.test({ name: "parse() handles error message", fn() { assertThrows( () => parse("foo = 1\nbar ="), TOMLParseError, "line 2, column 5", ); assertThrows( () => parse("foo = 1\nbar = 'foo\nbaz=1"), TOMLParseError, "line 2, column 10", ); assertThrows( () => parse(""), TOMLParseError, "line 1, column 0", ); assertThrows( () => ParserFactory((_s) => { throw "Custom parser"; })(""), TOMLParseError, "[non-error thrown]", ); },});
Deno.test({ name: "parse() handles strings", fn() { const expected = { strings: { str0: "deno", str1: "Roses are not Deno\n Violets are not Deno either", str2: "Roses are not Deno\nViolets are not Deno either", str3: "Roses are not Deno\r\nViolets are not Deno either", str4: 'this is a "quote"', str5: "The quick brown fox jumps over the lazy dog.", str6: "The quick brown fox jumps over the lazy dog.", str7: "Roses are red\tViolets are blue", str8: "Roses are red\fViolets are blue", str9: "Roses are red\bViolets are blue", str10: "Roses are red\\Violets are blue", str11: `double "quote"\nsingle 'quote'\n`, str12: 'Here are two quotation marks: "". Simple enough.', str13: 'Here are three quotation marks: """.', str14: 'Here are fifteen quotation marks: """"""""""""""".', str15: '"This," she said, "is just a pointless statement."', literal1: "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", literal2: '"\\n#=*{', literal3: "\\n\\t is 'literal'\\\n", literal4: 'Here are fifteen quotation marks: """""""""""""""', literal5: "Here are fifteen apostrophes: '''''''''''''''", literal6: "'That,' she said, 'is still pointless.'", withApostrophe: "What if it's not?", withSemicolon: `const message = 'hello world';`, withHexNumberLiteral: "Prevent bug from stripping string here ->0xabcdef", withUnicodeChar1: "あ", withUnicodeChar2: "Deno🦕", }, }; const actual = parseFile(path.join(testdataDir, "string.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles CRLF", fn() { const expected = { boolean: { bool1: true, bool2: false } }; const actual = parseFile(path.join(testdataDir, "CRLF.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles boolean", fn() { const expected = { boolean: { bool1: true, bool2: false, bool3: true } }; const actual = parseFile(path.join(testdataDir, "boolean.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles integer", fn() { const expected = { integer: { int1: 99, int2: 42, int3: 0, int4: -17, int5: 1000, int6: 5349221, int7: 12345, hex1: "0xDEADBEEF", hex2: "0xdeadbeef", hex3: "0xdead_beef", oct1: "0o01234567", oct2: "0o755", bin1: "0b11010110", }, }; const actual = parseFile(path.join(testdataDir, "integer.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles float", fn() { const expected = { float: { flt1: 1.0, flt2: 3.1415, flt3: -0.01, flt4: 5e22, flt5: 1e6, flt6: -2e-2, flt7: 6.626e-34, flt8: 224_617.445_991_228, sf1: Infinity, sf2: Infinity, sf3: -Infinity, sf4: NaN, sf5: NaN, sf6: NaN, }, }; const actual = parseFile(path.join(testdataDir, "float.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles arrays", fn() { const expected = { arrays: { data: [ ["gamma", "delta"], [1, 2], ], floats: [ 0.1, -1.25, ], hosts: ["alpha", "omega"], profiles: [ { "john@example.com": true, name: "John", }, { "doe@example.com": true, name: "Doe", }, ], }, }; const actual = parseFile(path.join(testdataDir, "arrays.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles table", fn() { const expected = { deeply: { nested: { object: { in: { the: { toml: { name: "Tom Preston-Werner", }, }, }, }, }, }, servers: { alpha: { ip: "10.0.0.1", dc: "eqdc10", }, beta: { ip: "10.0.0.2", dc: "eqdc20", }, }, dog: { "tater.man": { type: { name: "pug", }, }, }, }; const actual = parseFile(path.join(testdataDir, "table.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles various keys", fn() { const expected = { site: { "google.com": { bar: 1, baz: 1 } }, a: { b: { c: 1, d: 1 }, e: 1 }, "": 1, "127.0.0.1": 1, "ʎǝʞ": 1, 'this is "literal"': 1, 'double "quote"': 1, "basic__\n__": 1, "literal__\\n__": 1, }; const actual = parseFile(path.join(testdataDir, "keys.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles simple", fn() { const expected = { deno: "is", not: "[node]", regex: "<\\i\\c*\\s*>", NANI: "何?!", comment: "Comment inside # the comment", }; const actual = parseFile(path.join(testdataDir, "simple.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles datetime", fn() { const expected = { datetime: { odt1: new Date("1979-05-27T07:32:00Z"), odt2: new Date("1979-05-27T00:32:00-07:00"), odt3: new Date("1979-05-27T00:32:00.999999-07:00"), odt4: new Date("1979-05-27 07:32:00Z"), ld1: new Date("1979-05-27"), lt1: "07:32:00", lt2: "00:32:00.999999", }, }; const actual = parseFile(path.join(testdataDir, "datetime.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles inline table", fn() { const expected = { inlinetable: { nile: { also: { malevolant: { creation: { drum: { kit: "Tama", }, }, }, }, derek: { roddy: "drummer", }, }, name: { first: "Tom", last: "Preston-Werner", }, point: { x: 1, y: 2, }, dog: { type: { name: "pug", }, }, "tosin.abasi": "guitarist", animal: { as: { leaders: "tosin", }, }, annotation_filter: { "kubernetes.io/ingress.class": "nginx" }, literal_key: { "foo\\nbar": "foo\\nbar", }, nested: { parent: { "child.ren": [ "[", "]", ], children: [ "{", "}", ], }, }, empty: {}, }, }; const actual = parseFile(path.join(testdataDir, "inlineTable.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles array of tables", fn() { const expected = { bin: [ { name: "deno", path: "cli/main.rs" }, { name: "deno_core", path: "src/foo.rs" }, ], nib: [{ name: "node", path: "not_found" }], a: { c: { z: "z", }, }, b: [ { c: { z: "z", }, }, { c: { z: "z", }, }, ], aaa: [ { bbb: { asdf: "asdf", }, hi: "hi", }, ], }; const actual = parseFile(path.join(testdataDir, "arrayTable.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles cargo", fn() { const expected = { workspace: { members: ["./", "core"] }, bin: [{ name: "deno", path: "cli/main.rs" }], package: { name: "deno", version: "0.3.4", edition: "2018" }, dependencies: { deno_core: { path: "./core" }, atty: "0.2.11", dirs: "1.0.5", flatbuffers: "0.5.0", futures: "0.1.25", getopts: "0.2.18", http: "0.1.16", hyper: "0.12.24", "hyper-rustls": "0.16.0", "integer-atomics": "1.0.2", lazy_static: "1.3.0", libc: "0.2.49", log: "0.4.6", rand: "0.6.5", regex: "1.1.0", remove_dir_all: "0.5.2", ring: "0.14.6", rustyline: "3.0.0", serde_json: "1.0.38", "source-map-mappings": "0.5.0", tempfile: "3.0.7", tokio: "0.1.15", "tokio-executor": "0.1.6", "tokio-fs": "0.1.5", "tokio-io": "0.1.11", "tokio-process": "0.2.3", "tokio-threadpool": "0.1.11", url: "1.7.2", }, target: { "cfg(windows)": { dependencies: { winapi: "0.3.6" } }, "cfg(linux)": { dependencies: { winapi: "0.3.9" } }, }, }; const actual = parseFile(path.join(testdataDir, "cargo.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles stringify", fn() { const src = { foo: { bar: "deno" }, this: { is: { nested: "denonono" } }, "https://deno.land/std": { $: "dollar", }, "##": { deno: { "https://deno.land": { proto: "https", ":80": "port", }, }, }, arrayObjects: [{ stuff: "in" }, {}, { the: "array" }], deno: "is", not: "[node]", regex: "<ic*s*>", NANI: "何?!", comment: "Comment inside # the comment", int1: 99, int2: 42, int3: 0, int4: -17, int5: 1000, int6: 5349221, int7: 12345, flt1: 1.0, flt2: 3.1415, flt3: -0.01, flt4: 5e22, flt5: 1e6, flt6: -2e-2, flt7: 6.626e-34, odt1: new Date("1979-05-01T07:32:00Z"), odt2: new Date("1979-05-27T00:32:00-07:00"), odt3: new Date("1979-05-27T00:32:00.999999-07:00"), odt4: new Date("1979-05-27 07:32:00Z"), ld1: new Date("1979-05-27"), reg: /foo[bar]/, sf1: Infinity, sf2: Infinity, sf3: -Infinity, sf4: NaN, sf5: NaN, sf6: NaN, data: [ ["gamma", "delta"], [1, 2], ], hosts: ["alpha", "omega"], bool: true, bool2: false, }; const expected = `deno = "is"not = "[node]"regex = "<ic*s*>"NANI = "何?!"comment = "Comment inside # the comment"int1 = 99int2 = 42int3 = 0int4 = -17int5 = 1000int6 = 5349221int7 = 12345flt1 = 1flt2 = 3.1415flt3 = -0.01flt4 = 5e+22flt5 = 1000000flt6 = -0.02flt7 = 6.626e-34odt1 = 1979-05-01T07:32:00.000odt2 = 1979-05-27T07:32:00.000odt3 = 1979-05-27T07:32:00.999odt4 = 1979-05-27T07:32:00.000ld1 = 1979-05-27T00:00:00.000reg = "/foo[bar]/"sf1 = infsf2 = infsf3 = -infsf4 = NaNsf5 = NaNsf6 = NaNdata = [["gamma","delta"],[1,2]]hosts = ["alpha","omega"]bool = truebool2 = false
[foo]bar = "deno"
[this.is]nested = "denonono"
["https://deno.land/std"]"$" = "dollar"
["##".deno."https://deno.land"]proto = "https"":80" = "port"
[[arrayObjects]]stuff = "in"
[[arrayObjects]]
[[arrayObjects]]the = "array"`; const actual = stringify(src); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles mixed array", fn() { const src = { emptyArray: [], mixedArray1: [1, { b: 2 }], mixedArray2: [{ b: 2 }, 1], nestedArray1: [[{ b: 1, date: new Date("2022-05-13") }]], nestedArray2: [[[{ b: 1 }]]], nestedArray3: [[], [{ b: 1 }]], deepNested: { a: { b: [1, { c: 2, d: [{ e: 3 }, true] }], }, }, }; const expected = `emptyArray = []mixedArray1 = [1,{b = 2}]mixedArray2 = [{b = 2},1]nestedArray1 = [[{b = 1,date = "2022-05-13T00:00:00.000"}]]nestedArray2 = [[[{b = 1}]]]nestedArray3 = [[],[{b = 1}]]
[deepNested.a]b = [1,{c = 2,d = [{e = 3},true]}]`; const actual = stringify(src); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles stringify with string values", fn: () => { const src = { '"': '"', "'": "'", " ": " ", "\\": "\\", "\n": "\n", "\t": "\t", }; const expected = `"\\"" = "\\"""'" = "'"" " = " ""\\\\" = "\\\\""\\n" = "\\n""\\t" = "\\t"`.trim(); const actual = stringify(src).trim(); assertEquals(actual, expected); const parsed = parse(actual); assertEquals(src, parsed); },});
Deno.test({ name: "parse() handles comments", fn: () => { const expected = { str0: "value", str1: "# This is not a comment", str2: " # this is not a comment!\nA multiline string with a #\n# this is also not a comment\n", str3: '"# not a comment"\n\t# this is a real tab on purpose \n# not a comment\n', point0: { x: 1, y: 2, str0: "#not a comment", z: 3 }, point1: { x: 7, y: 8, z: 9, str0: "#not a comment" }, deno: { features: ["#secure by default", "supports typescript # not a comment"], url: "https://deno.land/", is_not_node: true, }, toml: { name: "Tom's Obvious, Minimal Language", objectives: ["easy to read", "minimal config file", "#not a comment"], }, }; const actual = parseFile(path.join(testdataDir, "comment.toml")); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles inline array of inline table", fn() { const expected = { inlineArray: { string: [{ var: "a string" }], my_points: [ { x: 1, y: 2, z: 3 }, { x: 7, y: 8, z: 9 }, { x: 2, y: 4, z: 8 }, ], points: [ { x: 1, y: 2, z: 3 }, { x: 7, y: 8, z: 9 }, { x: 2, y: 4, z: 8 }, ], }, }; const actual = parseFile( path.join(testdataDir, "inlineArrayOfInlineTable.toml"), ); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles parse malformed local time as string (#8433)", fn() { const expected = { sign: "2020-01-01x" }; const actual = parse(`sign='2020-01-01x'`); assertEquals(actual, expected); },});
Deno.test({ name: "parse() handles single-line string comment error", fn() { assertThrows( () => { parseFile(path.join(testdataDir, "error-open-string.toml")); }, Error, `Parse error on line 1, column 34: Single-line string cannot contain EOL`, ); },});
Deno.test({ name: "parse() handles invalid string format", fn() { assertThrows( () => { parseFile(path.join(testdataDir, "error-invalid-string.toml")); }, Error, `invalid data format`, ); },});
Deno.test({ name: "parse() handles invalid whitespaces", fn() { assertThrows( () => { parseFile(path.join(testdataDir, "error-invalid-whitespace1.toml")); }, Error, "Contains invalid whitespaces: `\\u3000`", ); assertThrows( () => { parseFile(path.join(testdataDir, "error-invalid-whitespace2.toml")); }, Error, "Contains invalid whitespaces: `\\u3000`", ); },});