yini-parser 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -0
- package/LICENSE +201 -0
- package/README.md +120 -0
- package/dist/src/YINI.js +122 -0
- package/dist/src/config/env.js +15 -0
- package/dist/src/core/ErrorDataHandler.js +207 -0
- package/dist/src/core/YINIVisitor.js +856 -0
- package/dist/src/core/objectBuilder.js +166 -0
- package/dist/src/core/types.js +36 -0
- package/dist/src/grammar/YiniLexer.js +370 -0
- package/dist/src/grammar/YiniParser.js +2106 -0
- package/dist/src/grammar/YiniParserVisitor.js +14 -0
- package/dist/src/index.js +189 -0
- package/dist/src/parseEntry.js +155 -0
- package/dist/src/parsers/extractHeaderParts.js +103 -0
- package/dist/src/parsers/extractSignificantYiniLine.js +68 -0
- package/dist/src/parsers/parseBoolean.js +12 -0
- package/dist/src/parsers/parseNull.js +11 -0
- package/dist/src/parsers/parseNumber.js +49 -0
- package/dist/src/parsers/parseSectionHeader.js +111 -0
- package/dist/src/parsers/parseString.js +40 -0
- package/dist/src/utils/pathAndFileName.js +15 -0
- package/dist/src/utils/string.js +97 -0
- package/dist/src/utils/system.js +23 -0
- package/dist/src/yiniHelpers.js +141 -0
- package/dist/tests/integration/1-core-parsing/parse-bigger-section-nesting-as-object.test.js +83 -0
- package/dist/tests/integration/1-core-parsing/parse-section-nesting-w-classic-markers.test.js +170 -0
- package/dist/tests/integration/1-core-parsing/parse-section-nesting-w-nsh-markers.test.js +27 -0
- package/dist/tests/integration/1-core-parsing/read some values from level 1 and 2.test.js +77 -0
- package/dist/tests/integration/1-core-parsing/throw on bad section heads.test.js +162 -0
- package/dist/tests/integration/10-special-validation-modes/validation-modes.test.js +38 -0
- package/dist/tests/integration/2-file-structure-and-error/able to parse mixed case filenames.test.js +72 -0
- package/dist/tests/integration/2-file-structure-and-error/throw error on bad file extensions.test.js +36 -0
- package/dist/tests/integration/2-file-structure-and-error/throw error parsing bad content.test.js +80 -0
- package/dist/tests/smoke/A-general-smoke.test.js +259 -0
- package/dist/tests/smoke/B-parse-inline-smoke.test.js +270 -0
- package/dist/tests/smoke/C-traverse-file-smoke.test.js +141 -0
- package/dist/tests/smoke/D-parse-file-smoke.test.js +134 -0
- package/dist/tests/unit/parsers/extractHeaderParts.unit.test.js +490 -0
- package/dist/tests/unit/parsers/parseSectionHeader-classic.unit.test.js +421 -0
- package/dist/tests/unit/parsers/parseSectionHeader-nsh.unit.test.js +436 -0
- package/dist/tests/unit/parsers/parseSectionHeader-throw-on-invalid.unit.test.js +168 -0
- package/dist/tests/unit/utils/utils-pathAndFileName.unit.test.js +80 -0
- package/dist/tests/unit/utils/utils-string.unit.test.js +185 -0
- package/dist/tests/unit/yiniHelpers.unit.test.js +306 -0
- package/package.json +94 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const src_1 = __importDefault(require("../../src"));
|
|
8
|
+
const env_1 = require("../../src/config/env");
|
|
9
|
+
const system_1 = require("../../src/utils/system");
|
|
10
|
+
/**
|
|
11
|
+
* General Smoke Tests.
|
|
12
|
+
*/
|
|
13
|
+
describe('General Smoke Tests:', () => {
|
|
14
|
+
const DIR_OF_FIXTURES = '../fixtures/smoke-fixtures/strings-with-paths';
|
|
15
|
+
const baseDir = path_1.default.join(__dirname, DIR_OF_FIXTURES);
|
|
16
|
+
beforeAll(() => { });
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
(0, system_1.debugPrint)('beforeAll');
|
|
19
|
+
// const isDebug = !!process.env.IS_DEBUG
|
|
20
|
+
// if (!isDebug) {
|
|
21
|
+
// console.log('process.env.IS_DEBUG is false, OK')
|
|
22
|
+
// } else {
|
|
23
|
+
// console.error('process.env.IS_DEBUG is true, FAIL')
|
|
24
|
+
// console.error(
|
|
25
|
+
// 'Detected that IS_DEBUG is true, is should be false when testing',
|
|
26
|
+
// )
|
|
27
|
+
// console.error('process.env.IS_DEBUG:')
|
|
28
|
+
// console.error(process.env.IS_DEBUG)
|
|
29
|
+
// throw Error('ERROR: A variable in ENV has wrong state')
|
|
30
|
+
// }
|
|
31
|
+
});
|
|
32
|
+
// Trivial test to see if everything is okey before moving on to "real" tests.
|
|
33
|
+
test('1. Trivial test case.', () => {
|
|
34
|
+
// Arrange.
|
|
35
|
+
const a = 3;
|
|
36
|
+
const b = 5;
|
|
37
|
+
// Act.
|
|
38
|
+
const result = a + b;
|
|
39
|
+
// Assert.
|
|
40
|
+
expect(result).toEqual(8);
|
|
41
|
+
});
|
|
42
|
+
test('2. Correctly parse a short YINI Example.', () => {
|
|
43
|
+
// Arrange.
|
|
44
|
+
const validYini = `^ sectionTitle
|
|
45
|
+
strVar = "Hello World!"
|
|
46
|
+
intVar = 98.21`;
|
|
47
|
+
// Act.
|
|
48
|
+
const result = src_1.default.parse(validYini);
|
|
49
|
+
(0, system_1.debugPrint)(result);
|
|
50
|
+
// Assert.
|
|
51
|
+
expect(result.sectionTitle.strVar).toEqual('Hello World!');
|
|
52
|
+
expect(result.sectionTitle.intVar).toEqual(98.21);
|
|
53
|
+
});
|
|
54
|
+
test('3. Should throw error if parsing some "garbage".', () => {
|
|
55
|
+
// Arrange.
|
|
56
|
+
const fixture = `someGarbage`;
|
|
57
|
+
// Act & Assert.
|
|
58
|
+
expect(() => {
|
|
59
|
+
src_1.default.parse(fixture);
|
|
60
|
+
}).toThrow();
|
|
61
|
+
});
|
|
62
|
+
test('4. Should throw error if parsing lines of "invalid" content.', () => {
|
|
63
|
+
// Arrange.
|
|
64
|
+
const fixture = `
|
|
65
|
+
古池や蛙飛び込む水の音
|
|
66
|
+
ふるいけやかわずとびこむみずのおと
|
|
67
|
+
furu ike ya kawazu tobikomu mizu no oto
|
|
68
|
+
`;
|
|
69
|
+
// Act & Assert.
|
|
70
|
+
expect(() => {
|
|
71
|
+
src_1.default.parse(fixture);
|
|
72
|
+
}).toThrow();
|
|
73
|
+
});
|
|
74
|
+
test('5. Should throw error if parsing unknown file name.', () => {
|
|
75
|
+
// Arrange.
|
|
76
|
+
const fullPath = 'gibberish-path-and-file-name';
|
|
77
|
+
// Act & Assert.
|
|
78
|
+
expect(() => {
|
|
79
|
+
(0, system_1.debugPrint)('fullPath = ' + fullPath);
|
|
80
|
+
src_1.default.parseFile(fullPath);
|
|
81
|
+
}).toThrow();
|
|
82
|
+
});
|
|
83
|
+
test('6. Should throw error if parsing "blank" content.', () => {
|
|
84
|
+
// Arrange.
|
|
85
|
+
const fixture = ' '; // NOTE: Only a blank space!
|
|
86
|
+
// Act & Assert.
|
|
87
|
+
expect(() => {
|
|
88
|
+
src_1.default.parse(fixture);
|
|
89
|
+
}).toThrow();
|
|
90
|
+
});
|
|
91
|
+
test('7. Correctly parse paths with forward slash "/".', () => {
|
|
92
|
+
// Arrange.
|
|
93
|
+
const fixture = `^ PathsWithSlash
|
|
94
|
+
path1 = '/'
|
|
95
|
+
path2 = '/etc'
|
|
96
|
+
path3 = 'etc/'
|
|
97
|
+
path4 = 'folder/subfolder'
|
|
98
|
+
path5 = '/usr/local/bin/'
|
|
99
|
+
`;
|
|
100
|
+
// Act.
|
|
101
|
+
const result = src_1.default.parse(fixture);
|
|
102
|
+
(0, system_1.debugPrint)(result);
|
|
103
|
+
// Assert.
|
|
104
|
+
expect(result.PathsWithSlash.path1).toEqual('/');
|
|
105
|
+
expect(result.PathsWithSlash.path2).toEqual('/etc');
|
|
106
|
+
expect(result.PathsWithSlash.path3).toEqual('etc/');
|
|
107
|
+
expect(result.PathsWithSlash.path4).toEqual('folder/subfolder');
|
|
108
|
+
expect(result.PathsWithSlash.path5).toEqual('/usr/local/bin/');
|
|
109
|
+
expect(result.PathsWithSlash.path1).not.toEqual('*');
|
|
110
|
+
});
|
|
111
|
+
test('8. Correctly parse paths with backslash "\\".', () => {
|
|
112
|
+
// Arrange.
|
|
113
|
+
const fileName = 'PathsWithBackslash.yini';
|
|
114
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
115
|
+
// Act.
|
|
116
|
+
const result = src_1.default.parseFile(fullPath);
|
|
117
|
+
(0, system_1.debugPrint)('fullPath = ' + fullPath);
|
|
118
|
+
(0, system_1.debugPrint)(result);
|
|
119
|
+
// Assert.
|
|
120
|
+
expect(result.PathsWithBackslash.path1).toEqual('\\');
|
|
121
|
+
expect(result.PathsWithBackslash.path2).toEqual('\\Temp');
|
|
122
|
+
expect(result.PathsWithBackslash.path3).toEqual('Temp\\');
|
|
123
|
+
expect(result.PathsWithBackslash.path4).toEqual('Windows\\System32');
|
|
124
|
+
expect(result.PathsWithBackslash.path5).toEqual('\\Users\\Public\\Documents\\');
|
|
125
|
+
expect(result.PathsWithBackslash.path1).not.toEqual('*');
|
|
126
|
+
});
|
|
127
|
+
test('9. Correctly parse paths with quotes and forward slash "/".', () => {
|
|
128
|
+
// Arrange.
|
|
129
|
+
const fileName = 'paths-w-quotes-and-slash.yini';
|
|
130
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
131
|
+
// Act.
|
|
132
|
+
const result = src_1.default.parseFile(fullPath);
|
|
133
|
+
(0, system_1.debugPrint)('fullPath = ' + fullPath);
|
|
134
|
+
(0, system_1.debugPrint)(result);
|
|
135
|
+
// Assert.
|
|
136
|
+
expect(result.PathsWithQuotesSlash.path1).toEqual("/'My Folder'/Documents/file.txt");
|
|
137
|
+
expect(result.PathsWithQuotesSlash.path2).toEqual('/"data"/set.csv');
|
|
138
|
+
expect(result.PathsWithQuotesSlash.path3).toEqual('/`Projects`/Code/'); // NOTE: Has backticks!
|
|
139
|
+
expect(result.PathsWithQuotesSlash.path1).not.toEqual('*');
|
|
140
|
+
});
|
|
141
|
+
test('10. Correctly parse paths with quotes and backslash "\\".', () => {
|
|
142
|
+
const DIR_OF_FIXTURES = '../fixtures/smoke-fixtures/strings-with-paths';
|
|
143
|
+
const baseDir = path_1.default.join(__dirname, DIR_OF_FIXTURES);
|
|
144
|
+
// Arrange.
|
|
145
|
+
const fileName = 'paths-w-quotes-and-backslash.yini';
|
|
146
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
147
|
+
// Act.
|
|
148
|
+
const result = src_1.default.parseFile(fullPath);
|
|
149
|
+
(0, system_1.debugPrint)('fullPath = ' + fullPath);
|
|
150
|
+
(0, system_1.debugPrint)(result);
|
|
151
|
+
// Assert.
|
|
152
|
+
expect(result.PathsWithQuotesBackslash.path1).toEqual("\\'Program Files'\\App\\");
|
|
153
|
+
expect(result.PathsWithQuotesBackslash.path2).toEqual('\\"user name"\\Desktop\\');
|
|
154
|
+
expect(result.PathsWithQuotesBackslash.path3).toEqual('\\Projects\\\`2024\`\\"Quarter 2"\\'); // NOTE: Has backticks!
|
|
155
|
+
expect(result.PathsWithQuotesBackslash.path1).not.toEqual('*');
|
|
156
|
+
});
|
|
157
|
+
test('11. Throw error if using section repeating markers higher than supported.', () => {
|
|
158
|
+
// Arrange.
|
|
159
|
+
const fixture1 = `^ Section1
|
|
160
|
+
^^ Section2
|
|
161
|
+
^^^ Section3
|
|
162
|
+
^^^^ Section4
|
|
163
|
+
^^^^^ Section5
|
|
164
|
+
^^^^^^ Section6 // Section 6.
|
|
165
|
+
strVar = "These section headers are valid!"
|
|
166
|
+
`;
|
|
167
|
+
const fixture2 = `^ Section1
|
|
168
|
+
^^ Section2
|
|
169
|
+
^^^ Section3
|
|
170
|
+
^^^^ Section4
|
|
171
|
+
^^^^^ Section5
|
|
172
|
+
^^^^^^ Section6 // Section 6.
|
|
173
|
+
^^^^^^^ Section7 // INVALID HEADER MARKER!
|
|
174
|
+
strVar = "^^^^^^^ (7) is invalid"
|
|
175
|
+
`;
|
|
176
|
+
// Act.
|
|
177
|
+
const result1 = src_1.default.parse(fixture1);
|
|
178
|
+
(0, env_1.isDebug)() && (0, system_1.printObject)(result1);
|
|
179
|
+
// Assert.
|
|
180
|
+
expect(!!result1).toEqual(true);
|
|
181
|
+
expect(result1.Section1.Section2.Section3.Section4.Section5.Section6
|
|
182
|
+
.strVar).toBe('These section headers are valid!');
|
|
183
|
+
// Act & Assert.
|
|
184
|
+
expect(() => {
|
|
185
|
+
src_1.default.parse(fixture2);
|
|
186
|
+
}).toThrow();
|
|
187
|
+
});
|
|
188
|
+
test('12. Should throw error if parsing an incorrect hash comment.', () => {
|
|
189
|
+
// Arrange.
|
|
190
|
+
const invalidYini = `^ App
|
|
191
|
+
id = 32403 #This hash comment is invalid due to a missing space.
|
|
192
|
+
title = "My Program"
|
|
193
|
+
`;
|
|
194
|
+
// Act & Assert.
|
|
195
|
+
expect(() => {
|
|
196
|
+
src_1.default.parse(invalidYini);
|
|
197
|
+
}).toThrow();
|
|
198
|
+
});
|
|
199
|
+
test('13. Correctly parse a YINI with a hash comment.', () => {
|
|
200
|
+
// Arrange.
|
|
201
|
+
const validYini = `^ App
|
|
202
|
+
id = 32403 # The correct app id.
|
|
203
|
+
title = "My Program"
|
|
204
|
+
`;
|
|
205
|
+
// Act.
|
|
206
|
+
(0, env_1.isDebug)() && (0, system_1.printObject)(validYini);
|
|
207
|
+
const result = src_1.default.parse(validYini);
|
|
208
|
+
(0, system_1.debugPrint)(result);
|
|
209
|
+
// Assert.
|
|
210
|
+
expect(result.App.id).toEqual(32403);
|
|
211
|
+
expect(result.App.title).toEqual('My Program');
|
|
212
|
+
});
|
|
213
|
+
test('14. Correctly parse a YINI enclosed in comments.', () => {
|
|
214
|
+
// Arrange.
|
|
215
|
+
const validYini = `
|
|
216
|
+
// This whole line is a comment.
|
|
217
|
+
^SectionName# This part is a comment.
|
|
218
|
+
// This whole line is a comment.
|
|
219
|
+
`;
|
|
220
|
+
// Act.
|
|
221
|
+
(0, env_1.isDebug)() && (0, system_1.printObject)(validYini);
|
|
222
|
+
const result = src_1.default.parse(validYini);
|
|
223
|
+
(0, env_1.isDebug)() && (0, system_1.printObject)(result);
|
|
224
|
+
// Assert.
|
|
225
|
+
expect(result).toHaveProperty('SectionName');
|
|
226
|
+
//@todo Fix issue that the below value will correctly be {} and not undefined
|
|
227
|
+
//expect(result.SectionName).toEqual({})
|
|
228
|
+
});
|
|
229
|
+
test('15. Should throw error due to illegal section name.', () => {
|
|
230
|
+
// Arrange.
|
|
231
|
+
const invalidYini = `// Should detect illegal section name 2SubSub1!!
|
|
232
|
+
^ App
|
|
233
|
+
^^ SubSect
|
|
234
|
+
^^^ 2SubSub1 // NOT OK, illegal name!
|
|
235
|
+
valueSS1 = "Something."
|
|
236
|
+
valueSS2 = OFF
|
|
237
|
+
`;
|
|
238
|
+
// Act & Assert.
|
|
239
|
+
expect(() => {
|
|
240
|
+
src_1.default.parse(invalidYini);
|
|
241
|
+
(0, system_1.debugPrint)(invalidYini);
|
|
242
|
+
}).toThrow();
|
|
243
|
+
});
|
|
244
|
+
test('16. Should throw error due to illegal section name.', () => {
|
|
245
|
+
// Arrange.
|
|
246
|
+
const invalidYini = `// Should detect illegal section name 2SubSub1!!
|
|
247
|
+
^ App
|
|
248
|
+
^^ \` lsdfkj lj\`
|
|
249
|
+
^^^ 2SubSub1 // NOT OK, illegal name!
|
|
250
|
+
valueSS1 = "Something."
|
|
251
|
+
valueSS2 = OFF
|
|
252
|
+
`;
|
|
253
|
+
// Act & Assert.
|
|
254
|
+
expect(() => {
|
|
255
|
+
src_1.default.parse(invalidYini);
|
|
256
|
+
(0, system_1.debugPrint)(invalidYini);
|
|
257
|
+
}).toThrow();
|
|
258
|
+
});
|
|
259
|
+
});
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Around 10 Parse-Inline (incl. literals) Smoke Tests
|
|
4
|
+
*
|
|
5
|
+
* To "quickly" test the main features and syntax of YINI.
|
|
6
|
+
* @note These samples/fixtures are different than the tests for parseFile(..).
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const src_1 = __importDefault(require("../../src"));
|
|
13
|
+
const system_1 = require("../../src/utils/system");
|
|
14
|
+
const fixture10Yini = `
|
|
15
|
+
^ AppConfig
|
|
16
|
+
name = "YINI Tester"
|
|
17
|
+
version = 1.0
|
|
18
|
+
|
|
19
|
+
^^ Settings
|
|
20
|
+
enable_feature = true
|
|
21
|
+
paths = ["/home/user", "/tmp"]
|
|
22
|
+
options: "opt1", "opt2", "opt3"
|
|
23
|
+
|
|
24
|
+
^^^ Advanced
|
|
25
|
+
triple = """multi
|
|
26
|
+
line
|
|
27
|
+
string"""
|
|
28
|
+
|
|
29
|
+
classic = C"Hello\tWorld\n"
|
|
30
|
+
hyper = H" foo
|
|
31
|
+
bar baz "
|
|
32
|
+
|
|
33
|
+
^ Metadata
|
|
34
|
+
author = 'Smoke Test'
|
|
35
|
+
created = null
|
|
36
|
+
/END
|
|
37
|
+
`;
|
|
38
|
+
/**
|
|
39
|
+
* Parse-Inline Smoke Tests.
|
|
40
|
+
*/
|
|
41
|
+
describe('Parse-Inline Smoke Tests:', () => {
|
|
42
|
+
beforeAll(() => { });
|
|
43
|
+
//@todo Need to fix so a single member is attached or returned with the implicit base object.
|
|
44
|
+
xtest('1.a. Shortest Valid Code (a single member).', () => {
|
|
45
|
+
// Arrange.
|
|
46
|
+
const validYini = 'number=42';
|
|
47
|
+
// Act.
|
|
48
|
+
const result = src_1.default.parse(validYini);
|
|
49
|
+
(0, system_1.debugPrint)(result);
|
|
50
|
+
// Assert.
|
|
51
|
+
expect(result.number).toEqual(42);
|
|
52
|
+
});
|
|
53
|
+
//@todo Fix so this get parse correctly, seems to be issue that {} is being transformed to undefined at some point!
|
|
54
|
+
xtest('1.b. Shortest Valid Code (a single section title).', () => {
|
|
55
|
+
// Arrange.
|
|
56
|
+
const validYini = '^Title';
|
|
57
|
+
// Act.
|
|
58
|
+
const result = src_1.default.parse(validYini);
|
|
59
|
+
(0, system_1.debugPrint)(result);
|
|
60
|
+
// Assert.
|
|
61
|
+
expect(result.Title).toBeDefined();
|
|
62
|
+
});
|
|
63
|
+
test('1.c. Shortest Valid Code (section with a single member).', () => {
|
|
64
|
+
// Arrange.
|
|
65
|
+
const validYini = `^title
|
|
66
|
+
another=64`;
|
|
67
|
+
// Act.
|
|
68
|
+
const result = src_1.default.parse(validYini);
|
|
69
|
+
(0, system_1.debugPrint)(result);
|
|
70
|
+
// Assert.
|
|
71
|
+
expect(result.title.another).toEqual(64);
|
|
72
|
+
});
|
|
73
|
+
test('2. Short Valid Code (tabbed section with a negative number).', () => {
|
|
74
|
+
// Arrange.
|
|
75
|
+
const validYini = `
|
|
76
|
+
\t^ Section
|
|
77
|
+
\tnumber = -1`;
|
|
78
|
+
// Act.
|
|
79
|
+
const result = src_1.default.parse(validYini);
|
|
80
|
+
(0, system_1.debugPrint)(result);
|
|
81
|
+
// Assert.
|
|
82
|
+
expect(result.Section.number).toEqual(-1);
|
|
83
|
+
});
|
|
84
|
+
test('3. Minimal Valid Code (section with couple of members).', () => {
|
|
85
|
+
// Arrange.
|
|
86
|
+
const validYini = `^ Main
|
|
87
|
+
name = 'YINI Smoke Test'
|
|
88
|
+
version = 3`;
|
|
89
|
+
// Act.
|
|
90
|
+
const result = src_1.default.parse(validYini);
|
|
91
|
+
(0, system_1.debugPrint)(result);
|
|
92
|
+
// Assert.
|
|
93
|
+
expect(result.Main.name).toEqual('YINI Smoke Test');
|
|
94
|
+
expect(result.Main.version).toEqual(3);
|
|
95
|
+
});
|
|
96
|
+
//@todo Needs implementing of section with sections for this pass.
|
|
97
|
+
xtest('4. Nested Sections, Tabbed Nesting, Backticked Names.', () => {
|
|
98
|
+
// Arrange.
|
|
99
|
+
const validYini = `@yini
|
|
100
|
+
^ user
|
|
101
|
+
username = "tester"
|
|
102
|
+
\`Is Admin\` = True
|
|
103
|
+
|
|
104
|
+
^^ prefs
|
|
105
|
+
theme = 'dark'
|
|
106
|
+
notifications = false
|
|
107
|
+
|
|
108
|
+
^^^ \`Complex Section\`
|
|
109
|
+
setting = 99`;
|
|
110
|
+
// Act.
|
|
111
|
+
const result = src_1.default.parse(validYini);
|
|
112
|
+
(0, system_1.debugPrint)(result);
|
|
113
|
+
// Assert.
|
|
114
|
+
expect(result.user.username).toEqual('tester');
|
|
115
|
+
expect(result.user.is_admin).toEqual(true);
|
|
116
|
+
expect(result.user.prefs.theme).toEqual('dark');
|
|
117
|
+
expect(result.user.prefs.notifications).toEqual(false);
|
|
118
|
+
expect(result.user.prefs.theme['Complex Section'].setting).toEqual(99);
|
|
119
|
+
});
|
|
120
|
+
test('5. All Key/Value (simple) Types.', () => {
|
|
121
|
+
// Arrange.
|
|
122
|
+
const validYini = `
|
|
123
|
+
^ TypesDemo
|
|
124
|
+
string1 = "Hello"
|
|
125
|
+
string2 = 'World'
|
|
126
|
+
number1 = 123
|
|
127
|
+
number2 = -5.7
|
|
128
|
+
hexval = 0xFFEE
|
|
129
|
+
|
|
130
|
+
binval = %10001
|
|
131
|
+
bool_true = yes
|
|
132
|
+
\`bool false\` = OFF
|
|
133
|
+
nullval = null
|
|
134
|
+
empty_val = # ← Null (lenient mode)`;
|
|
135
|
+
// Act.
|
|
136
|
+
const result = src_1.default.parse(validYini);
|
|
137
|
+
(0, system_1.debugPrint)(result);
|
|
138
|
+
// Assert.
|
|
139
|
+
expect(result.TypesDemo.string1).toEqual('Hello');
|
|
140
|
+
expect(result.TypesDemo.string2).toEqual('World');
|
|
141
|
+
expect(result.TypesDemo.number1).toEqual(123);
|
|
142
|
+
expect(result.TypesDemo.number2).toEqual(-5.7);
|
|
143
|
+
expect(result.TypesDemo.hexval).toEqual(65518);
|
|
144
|
+
expect(result.TypesDemo.binval).toEqual(17);
|
|
145
|
+
expect(result.TypesDemo.bool_true).toEqual(true);
|
|
146
|
+
expect(result.TypesDemo['bool false']).toEqual(false);
|
|
147
|
+
expect(result.TypesDemo.nullval).toEqual(null);
|
|
148
|
+
expect(result.TypesDemo.empty_val).toEqual(null);
|
|
149
|
+
//@todo Add the rest of the members too
|
|
150
|
+
});
|
|
151
|
+
xtest('6. List Types.', () => {
|
|
152
|
+
// Arrange.
|
|
153
|
+
const validYini = `
|
|
154
|
+
@YINI
|
|
155
|
+
^ Lists
|
|
156
|
+
simple = [1, 2, 3]
|
|
157
|
+
mixed = ["A", 10, true, null]
|
|
158
|
+
nested = [[1, 2], [3, 4]]
|
|
159
|
+
trailing = [5, 6, 7, ] // Trailing comma allowed in lenient mode
|
|
160
|
+
|
|
161
|
+
colonlist:
|
|
162
|
+
"a",
|
|
163
|
+
"b",
|
|
164
|
+
"c",`;
|
|
165
|
+
// Act.
|
|
166
|
+
const result = src_1.default.parse(validYini);
|
|
167
|
+
(0, system_1.debugPrint)(result);
|
|
168
|
+
// Assert.
|
|
169
|
+
//expect(result.TypesDemo.string2).toEqual('World')
|
|
170
|
+
//@todo Add the rest of the members too
|
|
171
|
+
});
|
|
172
|
+
xtest('7. Object Types.', () => {
|
|
173
|
+
// Arrange.
|
|
174
|
+
const validYini = `
|
|
175
|
+
^ Objects
|
|
176
|
+
person = { name = "Alice", age = 30, active = true }
|
|
177
|
+
nested = { inner = { foo = "bar" }, number = 2 }
|
|
178
|
+
empty = { }`;
|
|
179
|
+
// Act.
|
|
180
|
+
const result = src_1.default.parse(validYini);
|
|
181
|
+
(0, system_1.debugPrint)(result);
|
|
182
|
+
// Assert.
|
|
183
|
+
//expect(result.TypesDemo.string2).toEqual('World')
|
|
184
|
+
//@todo Add the rest of the members too
|
|
185
|
+
});
|
|
186
|
+
test('8. Comments, Block Comments, and Disabled Lines.', () => {
|
|
187
|
+
// Arrange.
|
|
188
|
+
const validYini = `
|
|
189
|
+
@yini
|
|
190
|
+
// Top comment
|
|
191
|
+
^ CommentsDemo
|
|
192
|
+
val1 = 123 # Inline comment
|
|
193
|
+
val2 = 456 // Another comment
|
|
194
|
+
; Full-line comment
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
Block comment
|
|
198
|
+
over multiple lines
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
--val3 = "This is disabled and ignored"
|
|
202
|
+
val4 = 'Some text.'
|
|
203
|
+
`;
|
|
204
|
+
// Act.
|
|
205
|
+
const result = src_1.default.parse(validYini);
|
|
206
|
+
(0, system_1.debugPrint)(result);
|
|
207
|
+
// Assert.
|
|
208
|
+
expect(result.CommentsDemo.val1).toEqual(123);
|
|
209
|
+
expect(result.CommentsDemo.val2).toEqual(456);
|
|
210
|
+
expect(result.CommentsDemo.val3).toEqual(undefined);
|
|
211
|
+
expect(result.CommentsDemo.val4).toEqual('Some text.');
|
|
212
|
+
});
|
|
213
|
+
test('9. Short-Hand and Alternative Section Notations', () => {
|
|
214
|
+
// Arrange.
|
|
215
|
+
const validYini = `
|
|
216
|
+
~ user
|
|
217
|
+
username = 'tester two'
|
|
218
|
+
isSysOp = YES
|
|
219
|
+
|
|
220
|
+
~~ prefs
|
|
221
|
+
theme = "light"
|
|
222
|
+
notifications = OFF
|
|
223
|
+
|
|
224
|
+
^1 user2
|
|
225
|
+
^2 prefs
|
|
226
|
+
^3 deepSection
|
|
227
|
+
^4 deeperSection
|
|
228
|
+
key = "Level 4 section"
|
|
229
|
+
^5 yetDeeperSection
|
|
230
|
+
key = "Level 5 section"
|
|
231
|
+
item = 77
|
|
232
|
+
|
|
233
|
+
~1 user3
|
|
234
|
+
username = 'tester three'
|
|
235
|
+
isSysOp = NO
|
|
236
|
+
|
|
237
|
+
~2 prefs
|
|
238
|
+
theme = "special-dark"
|
|
239
|
+
notifications = ON
|
|
240
|
+
|
|
241
|
+
`;
|
|
242
|
+
// Act.
|
|
243
|
+
const result = src_1.default.parse(validYini);
|
|
244
|
+
(0, system_1.debugPrint)(result);
|
|
245
|
+
// Assert.
|
|
246
|
+
expect(result.user.username).toEqual('tester two');
|
|
247
|
+
expect(result.user.isSysOp).toEqual(true);
|
|
248
|
+
expect(result.user.prefs.theme).toEqual('light');
|
|
249
|
+
expect(result.user.prefs.notifications).toEqual(false);
|
|
250
|
+
const deeperSection = Object.assign({}, result.user2.prefs.deepSection.deeperSection);
|
|
251
|
+
expect(deeperSection.key).toEqual('Level 4 section');
|
|
252
|
+
expect(deeperSection.yetDeeperSection.key).toEqual('Level 5 section');
|
|
253
|
+
expect(deeperSection.yetDeeperSection.item).toEqual(77);
|
|
254
|
+
expect(result.user3.username).toEqual('tester three');
|
|
255
|
+
expect(result.user3.isSysOp).toEqual(false);
|
|
256
|
+
//@todo (EDIT: This is fixed now??) Fix issue so this missing subsection gets included, not sure yet what exactly causes the issue...
|
|
257
|
+
expect(result.user3.prefs.theme).toEqual('special-dark');
|
|
258
|
+
expect(result.user3.prefs.notifications).toEqual(true);
|
|
259
|
+
});
|
|
260
|
+
//@todo Enable when can parse lists...
|
|
261
|
+
xtest('10. Parse inline AppConfig (Mixed).', () => {
|
|
262
|
+
// Arrange.
|
|
263
|
+
// Act.
|
|
264
|
+
const result = src_1.default.parse(fixture10Yini);
|
|
265
|
+
(0, system_1.debugPrint)(result);
|
|
266
|
+
// Assert.
|
|
267
|
+
expect(!!result).toEqual(true);
|
|
268
|
+
//@todo Add proper tests
|
|
269
|
+
});
|
|
270
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 10 Traverse-File Smoke Tests
|
|
4
|
+
*
|
|
5
|
+
* Dry run parsing, just analyzes/validates/traverses a set of real-life
|
|
6
|
+
* (mimiced) configuration files one might have.
|
|
7
|
+
*
|
|
8
|
+
* Dry-run parsing — performs only enough work to validate the input and
|
|
9
|
+
* return success.
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const src_1 = __importDefault(require("../../src"));
|
|
17
|
+
const system_1 = require("../../src/utils/system");
|
|
18
|
+
const DIR_OF_FIXTURES = '../fixtures/smoke-fixtures';
|
|
19
|
+
/**
|
|
20
|
+
* Parse File Smoke Tests.
|
|
21
|
+
*/
|
|
22
|
+
describe('Parse-File Smoke Tests:', () => {
|
|
23
|
+
// Dir with smoke fixtures.
|
|
24
|
+
const baseDir = path_1.default.join(__dirname, DIR_OF_FIXTURES);
|
|
25
|
+
beforeAll(() => { });
|
|
26
|
+
test('Parse file "1-web-server-configuration.*".', () => {
|
|
27
|
+
// Arrange.
|
|
28
|
+
const fileName = '1-web-server-configuration.smoke.yini';
|
|
29
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
30
|
+
// Act.
|
|
31
|
+
const result = src_1.default.parseFile(fullPath);
|
|
32
|
+
(0, system_1.debugPrint)('fullPath = ' + fullPath);
|
|
33
|
+
(0, system_1.debugPrint)(result);
|
|
34
|
+
// Assert.
|
|
35
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
36
|
+
expect(!!result).toEqual(true);
|
|
37
|
+
});
|
|
38
|
+
test('Parse file "2-user-profile-settings.*".', () => {
|
|
39
|
+
// Arrange.
|
|
40
|
+
const fileName = '2-user-profile-settings.smoke.yini';
|
|
41
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
42
|
+
// Act.
|
|
43
|
+
const result = src_1.default.parseFile(fullPath);
|
|
44
|
+
(0, system_1.debugPrint)(result);
|
|
45
|
+
// Assert.
|
|
46
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
47
|
+
expect(!!result).toEqual(true);
|
|
48
|
+
});
|
|
49
|
+
//@todo Enable test (after can parse list (colon based)).
|
|
50
|
+
xtest('Parse file "3-cli-application-options.*".', () => {
|
|
51
|
+
// Arrange.
|
|
52
|
+
const fileName = '3-cli-application-options.smoke.yini';
|
|
53
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
54
|
+
// Act.
|
|
55
|
+
const result = src_1.default.parseFile(fullPath);
|
|
56
|
+
(0, system_1.debugPrint)(result);
|
|
57
|
+
// Assert.
|
|
58
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
59
|
+
expect(!!result).toEqual(true);
|
|
60
|
+
});
|
|
61
|
+
test('Parse file "4-build-project-configuration.*".', () => {
|
|
62
|
+
// Arrange.
|
|
63
|
+
const fileName = '4-build-project-configuration.smoke.yini';
|
|
64
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
65
|
+
// Act.
|
|
66
|
+
const result = src_1.default.parseFile(fullPath);
|
|
67
|
+
(0, system_1.debugPrint)(result);
|
|
68
|
+
// Assert.
|
|
69
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
70
|
+
expect(!!result).toEqual(true);
|
|
71
|
+
});
|
|
72
|
+
test('Parse file "5-database-connection.*".', () => {
|
|
73
|
+
// Arrange.
|
|
74
|
+
const fileName = '5-database-connection.smoke.yini';
|
|
75
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
76
|
+
// Act.
|
|
77
|
+
const result = src_1.default.parseFile(fullPath);
|
|
78
|
+
(0, system_1.debugPrint)(result);
|
|
79
|
+
// Assert.
|
|
80
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
81
|
+
expect(!!result).toEqual(true);
|
|
82
|
+
});
|
|
83
|
+
test('Parse file "6-feature-flags-example.*".', () => {
|
|
84
|
+
// Arrange.
|
|
85
|
+
const fileName = '6-feature-flags-example.smoke.yini';
|
|
86
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
87
|
+
// Act.
|
|
88
|
+
const result = src_1.default.parseFile(fullPath);
|
|
89
|
+
(0, system_1.debugPrint)(result);
|
|
90
|
+
// Assert.
|
|
91
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
92
|
+
expect(!!result).toEqual(true);
|
|
93
|
+
});
|
|
94
|
+
test('Parse file "7-email-smtp-configuration.*".', () => {
|
|
95
|
+
// Arrange.
|
|
96
|
+
const fileName = '7-email-smtp-configuration.smoke.yini';
|
|
97
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
98
|
+
// Act.
|
|
99
|
+
const result = src_1.default.parseFile(fullPath);
|
|
100
|
+
(0, system_1.debugPrint)(result);
|
|
101
|
+
// Assert.
|
|
102
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
103
|
+
expect(!!result).toEqual(true);
|
|
104
|
+
});
|
|
105
|
+
//@todo Enable test (after can parse colon based lists).
|
|
106
|
+
xtest('Parse file "8-api-keys-integration.*".', () => {
|
|
107
|
+
// Arrange.
|
|
108
|
+
const fileName = '8-api-keys-integration.smoke.yini';
|
|
109
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
110
|
+
// Act.
|
|
111
|
+
const result = src_1.default.parseFile(fullPath);
|
|
112
|
+
(0, system_1.debugPrint)(result);
|
|
113
|
+
// Assert.
|
|
114
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
115
|
+
expect(!!result).toEqual(true);
|
|
116
|
+
});
|
|
117
|
+
//@todo Enable test (after can parse with no section defined, implicit base object).
|
|
118
|
+
xtest('Parse file "9-app-preferences.*".', () => {
|
|
119
|
+
// Arrange.
|
|
120
|
+
const fileName = '9-app-preferences.smoke.yini';
|
|
121
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
122
|
+
// Act.
|
|
123
|
+
const result = src_1.default.parseFile(fullPath);
|
|
124
|
+
(0, system_1.debugPrint)(result);
|
|
125
|
+
// Assert.
|
|
126
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
127
|
+
expect(!!result).toEqual(true);
|
|
128
|
+
});
|
|
129
|
+
//@todo Enable test (after can parse lists)
|
|
130
|
+
xtest('Parse file "10-logging-monitoring.*".', () => {
|
|
131
|
+
// Arrange.
|
|
132
|
+
const fileName = '10-logging-monitoring.smoke.yini';
|
|
133
|
+
const fullPath = path_1.default.join(baseDir, fileName);
|
|
134
|
+
// Act.
|
|
135
|
+
const result = src_1.default.parseFile(fullPath);
|
|
136
|
+
(0, system_1.debugPrint)(result);
|
|
137
|
+
// Assert.
|
|
138
|
+
// NOTE: Dry run parsing - enough that something is successfully returned.
|
|
139
|
+
expect(!!result).toEqual(true);
|
|
140
|
+
});
|
|
141
|
+
});
|