Skip to main content
Module

std/toml/parse_test.ts

Deno standard library
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
// 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 } from "./parse.ts";
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]", ); },});