FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Add runtime resource parser + Improve CST resource parser by eemeli · Pull Request #471 · messageformat/messageformat · GitHub

Repository navigation

231 changes: 195 additions & 36 deletions mf2/resource/src/cst-parser.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,17 @@ function parseFail(source: string) {

test('empty string', () => {
const res = parseOk('');
expect(res).toMatchObject<TestResource>([
{ type: 'empty-line', range: [0, 0] }
]);
expect(res).toEqual<TestResource>([{ type: 'empty-line', range: [0, 0] }]);
});

test('single line terminator', () => {
const res = parseOk('\r\n');
expect(res).toMatchObject<TestResource>([
{ type: 'empty-line', range: [0, 2] }
]);
expect(res).toEqual<TestResource>([{ type: 'empty-line', range: [0, 2] }]);
});

test('comments and empty lines', () => {
const res = parseOk('\n\n#[foo\\] \n## bar\r\n \t\n#');
expect(res).toMatchObject<TestResource>([
expect(res).toEqual<TestResource>([
{ type: 'empty-line', range: [0, 1] },
{ type: 'empty-line', range: [1, 2] },
{ type: 'comment', content: '[foo\\] ', range: [2, 11] },
Expand All @@ -53,9 +49,81 @@ test('comments and empty lines', () => {
]);
});

test('frontmatter', () => {
const res = parseOk('@locale en-ZZ\n---\n');
expect(res).toEqual<TestResource>([
{
type: 'metadata',
key: {
range: [1, 7],
raw: [{ range: [1, 7], type: 'content', value: 'locale' }],
value: 'locale'
},
range: [0, 14],
value: {
range: [8, 13],
raw: [[{ range: [8, 13], type: 'content', value: 'en-ZZ' }]],
value: 'en-ZZ'
}
},
{ range: [14, 18], type: 'frontmatter' }
]);
});

test('empty entries', () => {
const res = parseOk('foo = \nbar =\nbaz=');
expect(res).toEqual<TestResource>([
{
type: 'entry',
id: {
raw: [{ type: 'content', value: 'foo', range: [0, 3] }],
value: ['foo'],
range: [0, 3]
},
equal: 4,
value: {
raw: [],
value: '',
range: [5, 5]
},
range: [0, 7]
},
{
type: 'entry',
id: {
raw: [{ type: 'content', value: 'bar', range: [7, 10] }],
value: ['bar'],
range: [7, 10]
},
equal: 11,
value: {
raw: [],
value: '',
range: [12, 12]
},
range: [7, 13]
},
{
type: 'entry',
id: {
raw: [{ type: 'content', value: 'baz', range: [13, 16] }],
value: ['baz'],
range: [13, 16]
},
equal: 16,
value: {
raw: [],
value: '',
range: [17, 17]
},
range: [13, 17]
}
]);
});

test('one-line entry', () => {
const res = parseOk('foo = {bar}');
expect(res).toMatchObject<TestResource>([
expect(res).toEqual<TestResource>([
{
type: 'entry',
id: {
Expand All @@ -76,7 +144,7 @@ test('one-line entry', () => {

test('multi-line entry', () => {
const res = parseOk('foo = \n {\n bar\n }\nnext={value}');
expect(res).toMatchObject<TestResource>([
expect(res).toEqual<TestResource>([
{
type: 'entry',
id: {
Expand All @@ -92,7 +160,7 @@ test('multi-line entry', () => {
[{ type: 'content', value: 'bar', range: [15, 18] }],
[{ type: 'content', value: '}', range: [21, 22] }]
],
value: '{\n bar\n }',
value: '{\nbar\n}',
range: [9, 22]
},
range: [0, 23]
Expand All @@ -115,9 +183,47 @@ test('multi-line entry', () => {
]);
});

test('multi-line entry with empty lines', () => {
const res = parseOk('foo = \n\n {\n\n bar\n }\n\nnext={value}');
expect(res).toMatchObject<TestResource>([
{
type: 'entry',
id: {
raw: [{ type: 'content', value: 'foo' }],
value: ['foo']
},
equal: 4,
value: {
raw: [
[],
[],
[{ type: 'content', value: '{' }],
[],
[{ type: 'content', value: 'bar' }],
[{ type: 'content', value: '}' }]
],
value: '{\n\nbar\n}'
}
},
{ type: 'empty-line' },
{
type: 'entry',
id: {
raw: [{ type: 'content', value: 'next' }],
value: ['next']
},
equal: 30,
value: {
raw: [[{ type: 'content', value: '{value}' }]],
value: '{value}'
}
}
]);
});

test('multi-line entry with CRLF terminators', () => {
const res = parseOk('foo = \r\n {\r\n bar\r\n }\r\n');
expect(res).toMatchObject<TestResource>([
expect(res).toEqual<TestResource>([
{
type: 'entry',
id: {
Expand All @@ -133,7 +239,8 @@ test('multi-line entry with CRLF terminators', () => {
[{ type: 'content', value: 'bar', range: [17, 20] }],
[{ type: 'content', value: '}', range: [24, 25] }]
],
value: '{\r\n bar\r\n }'
value: '{\nbar\n}',
range: [10, 25]
},
range: [0, 27]
}
Expand All @@ -142,7 +249,7 @@ test('multi-line entry with CRLF terminators', () => {

test('section-head with trailing whitespace', () => {
const res = parseOk('[ foo . bar ] \t\n');
expect(res).toMatchObject<TestResource>([
expect(res).toEqual<TestResource>([
{
type: 'section-head',
id: {
Expand Down Expand Up @@ -207,7 +314,7 @@ test('escaped contents', () => {
{ type: 'content', value: 'lines}' }
]
],
value: '{\\{msg\\|\\nlines}'
value: '{\\{msg\\|\nlines}'
}
}
]);
Expand All @@ -233,10 +340,10 @@ describe('duplicate identifiers', () => {
value: { raw: [[{ type: 'content', value: '3' }]] }
}
]);
expect(calls).toMatchObject([
[(res[0] as CST.Entry).id.range, 'Duplicate identifier'],
[(res[1] as CST.Entry).id.range, 'Duplicate identifier'],
[(res[2] as CST.Entry).id.range, 'Duplicate identifier']
expect(calls).toEqual([
[(res[0] as CST.Entry).id.range, 'Message already defined'],
[(res[1] as CST.Entry).id.range, 'Message already defined'],
[(res[2] as CST.Entry).id.range, 'Message already defined']
]);
});

Expand Down Expand Up @@ -282,7 +389,7 @@ describe('duplicate identifiers', () => {
},
{ type: 'section-head', id: { value: ['a', 'b'] } }
]);
expect(calls).toMatchObject([
expect(calls).toEqual([
[
(res[0] as CST.Entry).id.range,
'Shorter matching identifier must precede longer one'
Expand All @@ -309,9 +416,9 @@ describe('errors', () => {
value: { raw: [[{ type: 'content', value: 'foo\u2028bar' }]] }
}
]);
expect(calls).toMatchObject([
[[0, 1], 'Invalid identifier character'],
[[8, 9], 'Invalid entry content character']
expect(calls).toEqual([
[[0, 1], 'Invalid entry identifier: Unsupported character'],
[[8, 9], 'Invalid entry value']
]);
});

Expand All @@ -320,10 +427,62 @@ describe('errors', () => {
expect(res).toMatchObject<TestResource>([
{
type: 'section-head',
id: { raw: [], value: [], range: [2, 2] }
id: { raw: [], value: [], range: [2, 3] }
}
]);
expect(calls).toMatchObject([[[2, 3], 'Expected an identifier']]);
expect(calls).toEqual([[[2, 3], 'Invalid section identifier']]);
});

test('metadata without key', () => {
const [res, calls] = parseFail('@ x');
expect(res).toEqual<TestResource>([
{
type: 'metadata',
key: { range: [1, 2], raw: [], value: '' },
value: {
raw: [[{ range: [2, 3], type: 'content', value: 'x' }]],
value: 'x',
range: [2, 3]
},
range: [0, 3]
}
]);
expect(calls).toEqual([[[1, 2], 'Expected a metadata key']]);
});

test('metadata with no whitespace between key & value', () => {
const [res, calls] = parseFail('@x.foo');
expect(res).toEqual<TestResource>([
{
type: 'metadata',
key: {
raw: [{ range: [1, 2], type: 'content', value: 'x' }],
value: 'x',
range: [1, 2]
},
value: { range: [2, 2], raw: [], value: '' },
range: [0, 2]
},
{
type: 'entry',
id: {
range: [2, 6],
raw: [
{ range: [2, 3], type: 'dot' },
{ range: [3, 6], type: 'content', value: 'foo' }
],
value: ['foo']
},
equal: -1,
value: { range: [6, 6], raw: [], value: '' },
range: [2, 6]
}
]);
expect(calls).toEqual([
[[2, 6], 'Invalid metadata: Unexpected content at line end'],
[[2, 3], 'Invalid entry identifier: Leading dot'],
[[6, 7], 'Expected a = character here']
]);
});

test('identifier dots', () => {
Expand All @@ -340,10 +499,10 @@ describe('errors', () => {
}
}
]);
expect(calls).toMatchObject([
[[1, 2], 'Leading dot in identifier'],
[[1, 3], 'Repeated dots in identifier'],
[[2, 3], 'Trailing dot in identifier']
expect(calls).toEqual([
[[1, 2], 'Invalid section identifier: Leading dot'],
[[1, 3], 'Invalid section identifier: Repeated dots'],
[[2, 3], 'Invalid section identifier: Trailing dot']
]);
});

Expand All @@ -361,8 +520,8 @@ describe('errors', () => {
}
}
]);
expect(calls).toMatchObject([
[[2, 3], 'Unexpected whitespace in identifier']
expect(calls).toEqual([
[[2, 3], 'Invalid section identifier: Unexpected whitespace']
]);
});

Expand Down Expand Up @@ -391,7 +550,7 @@ describe('errors', () => {
}
}
]);
expect(calls).toMatchObject([
expect(calls).toEqual([
[[0, 2], 'Unknown character escape'],
[[4, 6], 'Unknown character escape'],
[[7, 9], 'Unknown character escape'],
Expand Down Expand Up @@ -425,9 +584,9 @@ describe('errors', () => {
value: { raw: [[{ type: 'content', value: '] d', range: [7, 10] }]] }
}
]);
expect(calls).toMatchObject([
expect(calls).toEqual([
[[2, 3], 'Expected a ] character here'],
[[4, 5], 'Unexpected whitespace in identifier'],
[[4, 5], 'Invalid entry identifier: Unexpected whitespace'],
[[7, 8], 'Expected a = character here']
]);
});
Expand All @@ -448,9 +607,9 @@ describe('errors', () => {
},
{ type: 'comment', content: 'd', range: [9, 11] }
]);
expect(calls).toMatchObject([
[[2, 4], 'Content with unexpected indent'],
[[9, 11], 'Unexpected content at line end']
expect(calls).toEqual([
[[2, 4], 'Invalid indent'],
[[9, 11], 'Invalid section identifier: Unexpected content at line end']
]);
});
});
Loading
Loading

Back | FazBrowse Home | New Git URL