hocon 0.9.5 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -2
- data/README.md +22 -10
- data/lib/hocon.rb +9 -3
- data/lib/hocon/config_factory.rb +4 -0
- data/lib/hocon/config_value_factory.rb +13 -2
- data/lib/hocon/impl/config_reference.rb +5 -2
- data/lib/hocon/impl/simple_config_origin.rb +1 -1
- data/spec/fixtures/parse_render/example1/input.conf +21 -0
- data/spec/fixtures/parse_render/example1/output.conf +26 -0
- data/spec/fixtures/parse_render/example1/output_nocomments.conf +17 -0
- data/spec/fixtures/parse_render/example2/input.conf +10 -0
- data/spec/fixtures/parse_render/example2/output.conf +17 -0
- data/spec/fixtures/parse_render/example2/output_nocomments.conf +17 -0
- data/spec/fixtures/parse_render/example3/input.conf +2 -0
- data/spec/fixtures/parse_render/example3/output.conf +2 -0
- data/spec/fixtures/parse_render/example4/input.json +6 -0
- data/spec/fixtures/parse_render/example4/output.conf +6 -0
- data/spec/fixtures/test_utils/resources/bom.conf +2 -0
- data/spec/fixtures/test_utils/resources/cycle.conf +1 -0
- data/spec/fixtures/test_utils/resources/file-include.conf +5 -0
- data/spec/fixtures/test_utils/resources/include-from-list.conf +4 -0
- data/spec/fixtures/test_utils/resources/subdir/bar.conf +1 -0
- data/spec/fixtures/test_utils/resources/subdir/baz.conf +1 -0
- data/spec/fixtures/test_utils/resources/subdir/foo.conf +5 -0
- data/spec/fixtures/test_utils/resources/test01.conf +80 -0
- data/spec/fixtures/test_utils/resources/test01.json +4 -0
- data/spec/fixtures/test_utils/resources/test03.conf +36 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/test_utils.rb +757 -0
- data/spec/unit/typesafe/config/concatenation_spec.rb +417 -0
- data/spec/unit/typesafe/config/conf_parser_spec.rb +822 -0
- data/spec/unit/typesafe/config/config_document_parser_spec.rb +494 -0
- data/spec/unit/typesafe/config/config_document_spec.rb +576 -0
- data/spec/unit/typesafe/config/config_factory_spec.rb +120 -0
- data/spec/unit/typesafe/config/config_node_spec.rb +552 -0
- data/spec/unit/typesafe/config/config_value_factory_spec.rb +85 -0
- data/spec/unit/typesafe/config/config_value_spec.rb +935 -0
- data/spec/unit/typesafe/config/hocon_spec.rb +54 -0
- data/spec/unit/typesafe/config/path_spec.rb +261 -0
- data/spec/unit/typesafe/config/public_api_spec.rb +520 -0
- data/spec/unit/typesafe/config/simple_config_spec.rb +112 -0
- data/spec/unit/typesafe/config/token_spec.rb +188 -0
- data/spec/unit/typesafe/config/tokenizer_spec.rb +801 -0
- metadata +39 -3
@@ -0,0 +1,576 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'hocon'
|
5
|
+
require 'hocon/parser/config_document_factory'
|
6
|
+
require 'hocon/config_value_factory'
|
7
|
+
require 'test_utils'
|
8
|
+
|
9
|
+
describe "ConfigDocument" do
|
10
|
+
ConfigDocumentFactory = Hocon::Parser::ConfigDocumentFactory
|
11
|
+
ConfigParseOptions = Hocon::ConfigParseOptions
|
12
|
+
ConfigSyntax = Hocon::ConfigSyntax
|
13
|
+
SimpleConfigDocument = Hocon::Impl::SimpleConfigDocument
|
14
|
+
ConfigValueFactory = Hocon::ConfigValueFactory
|
15
|
+
|
16
|
+
shared_examples_for "config document replace JSON test" do
|
17
|
+
let (:config_document) { ConfigDocumentFactory.parse_string(orig_text, ConfigParseOptions.defaults.set_syntax(ConfigSyntax::JSON)) }
|
18
|
+
it "should correctly render the parsed JSON document" do
|
19
|
+
expect(config_document.render).to eq(orig_text)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should perform a successful replacement on the parsed JSON document" do
|
23
|
+
new_document = config_document.set_value(replace_path, new_value)
|
24
|
+
#expect(new_document).to be_a(SimpleConfigDocument)
|
25
|
+
expect(new_document.render).to eq(final_text)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
shared_examples_for "config document replace CONF test" do
|
30
|
+
let (:config_document) { ConfigDocumentFactory.parse_string(orig_text) }
|
31
|
+
it "should correctly render the parsed CONF document" do
|
32
|
+
expect(config_document.render).to eq(orig_text)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should perform a successful replacement on the parsed CONF document" do
|
36
|
+
new_document = config_document.set_value(replace_path, new_value)
|
37
|
+
#expect(new_document).to be_a(SimpleConfigDocument)
|
38
|
+
expect(new_document.render).to eq(final_text)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "ConfigDocument replace" do
|
43
|
+
let (:orig_text) {
|
44
|
+
'{
|
45
|
+
"a":123,
|
46
|
+
"b": 123.456,
|
47
|
+
"c": true,
|
48
|
+
"d": false,
|
49
|
+
"e": null,
|
50
|
+
"f": "a string",
|
51
|
+
"g": [1,2,3,4,5],
|
52
|
+
"h": {
|
53
|
+
"a": 123,
|
54
|
+
"b": {
|
55
|
+
"a": 12
|
56
|
+
},
|
57
|
+
"c": [1, 2, 3, {"a": "b"}, [1,2,3]]
|
58
|
+
}
|
59
|
+
}'
|
60
|
+
}
|
61
|
+
context "parsing/replacement with a very simple map" do
|
62
|
+
let(:orig_text) { '{"a":1}' }
|
63
|
+
let(:final_text) { '{"a":2}' }
|
64
|
+
let (:new_value) { "2" }
|
65
|
+
let (:replace_path) { "a" }
|
66
|
+
include_examples "config document replace CONF test"
|
67
|
+
include_examples "config document replace JSON test"
|
68
|
+
end
|
69
|
+
|
70
|
+
context "parsing/replacement with a map without surrounding braces" do
|
71
|
+
let (:orig_text) { "a: b\nc = d" }
|
72
|
+
let (:final_text) { "a: b\nc = 12" }
|
73
|
+
let (:new_value) { "12" }
|
74
|
+
let (:replace_path) { "c" }
|
75
|
+
include_examples "config document replace CONF test"
|
76
|
+
end
|
77
|
+
|
78
|
+
context "parsing/replacement with a complicated map" do
|
79
|
+
let (:final_text) {
|
80
|
+
'{
|
81
|
+
"a":123,
|
82
|
+
"b": 123.456,
|
83
|
+
"c": true,
|
84
|
+
"d": false,
|
85
|
+
"e": null,
|
86
|
+
"f": "a string",
|
87
|
+
"g": [1,2,3,4,5],
|
88
|
+
"h": {
|
89
|
+
"a": 123,
|
90
|
+
"b": {
|
91
|
+
"a": "i am now a string"
|
92
|
+
},
|
93
|
+
"c": [1, 2, 3, {"a": "b"}, [1,2,3]]
|
94
|
+
}
|
95
|
+
}'
|
96
|
+
}
|
97
|
+
let (:new_value) { '"i am now a string"' }
|
98
|
+
let (:replace_path) { "h.b.a" }
|
99
|
+
include_examples "config document replace CONF test"
|
100
|
+
include_examples "config document replace JSON test"
|
101
|
+
end
|
102
|
+
|
103
|
+
context "replacing values with maps" do
|
104
|
+
let (:final_text) {
|
105
|
+
'{
|
106
|
+
"a":123,
|
107
|
+
"b": 123.456,
|
108
|
+
"c": true,
|
109
|
+
"d": false,
|
110
|
+
"e": null,
|
111
|
+
"f": "a string",
|
112
|
+
"g": [1,2,3,4,5],
|
113
|
+
"h": {
|
114
|
+
"a": 123,
|
115
|
+
"b": {
|
116
|
+
"a": {"a":"b", "c":"d"}
|
117
|
+
},
|
118
|
+
"c": [1, 2, 3, {"a": "b"}, [1,2,3]]
|
119
|
+
}
|
120
|
+
}' }
|
121
|
+
let (:new_value) { '{"a":"b", "c":"d"}' }
|
122
|
+
let (:replace_path) { "h.b.a" }
|
123
|
+
include_examples "config document replace CONF test"
|
124
|
+
include_examples "config document replace JSON test"
|
125
|
+
end
|
126
|
+
|
127
|
+
context "replacing values with arrays" do
|
128
|
+
let (:final_text) {
|
129
|
+
'{
|
130
|
+
"a":123,
|
131
|
+
"b": 123.456,
|
132
|
+
"c": true,
|
133
|
+
"d": false,
|
134
|
+
"e": null,
|
135
|
+
"f": "a string",
|
136
|
+
"g": [1,2,3,4,5],
|
137
|
+
"h": {
|
138
|
+
"a": 123,
|
139
|
+
"b": {
|
140
|
+
"a": [1,2,3,4,5]
|
141
|
+
},
|
142
|
+
"c": [1, 2, 3, {"a": "b"}, [1,2,3]]
|
143
|
+
}
|
144
|
+
}' }
|
145
|
+
let (:new_value) { "[1,2,3,4,5]" }
|
146
|
+
let (:replace_path) { "h.b.a" }
|
147
|
+
include_examples "config document replace CONF test"
|
148
|
+
include_examples "config document replace JSON test"
|
149
|
+
end
|
150
|
+
|
151
|
+
context "replacing values with concatenations" do
|
152
|
+
let (:final_text) {
|
153
|
+
'{
|
154
|
+
"a":123,
|
155
|
+
"b": 123.456,
|
156
|
+
"c": true,
|
157
|
+
"d": false,
|
158
|
+
"e": null,
|
159
|
+
"f": "a string",
|
160
|
+
"g": [1,2,3,4,5],
|
161
|
+
"h": {
|
162
|
+
"a": 123,
|
163
|
+
"b": {
|
164
|
+
"a": this is a concatenation 123 456 {a:b} [1,2,3] {a: this is another 123 concatenation null true}
|
165
|
+
},
|
166
|
+
"c": [1, 2, 3, {"a": "b"}, [1,2,3]]
|
167
|
+
}
|
168
|
+
}' }
|
169
|
+
let (:new_value) { "this is a concatenation 123 456 {a:b} [1,2,3] {a: this is another 123 concatenation null true}" }
|
170
|
+
let (:replace_path) { "h.b.a" }
|
171
|
+
include_examples "config document replace CONF test"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "config document multi element duplicates removed" do
|
176
|
+
it "should remove all duplicates when setting a value" do
|
177
|
+
orig_text = "{a: b, a.b.c: d, a: e}"
|
178
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text)
|
179
|
+
expect(config_doc.set_value("a", "2").render).to eq("{a: 2}")
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should keep a trailing comma if succeeding elements were removed in CONF" do
|
183
|
+
orig_text = "{a: b, a: e, a.b.c: d}"
|
184
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text)
|
185
|
+
expect(config_doc.set_value("a", "2").render).to eq("{a: 2, }")
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should add the setting if only a multi-element duplicate exists" do
|
189
|
+
orig_text = "{a.b.c: d}"
|
190
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text)
|
191
|
+
expect(config_doc.set_value("a", "2").render).to eq("{ a : 2}")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "config document set new value brace root" do
|
196
|
+
let (:orig_text) { "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n}" }
|
197
|
+
let (:new_value) { "\"f\"" }
|
198
|
+
let (:replace_path) { "\"e\"" }
|
199
|
+
|
200
|
+
context "set a new value in CONF" do
|
201
|
+
let (:final_text) { "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n\t\"e\" : \"f\"\n}" }
|
202
|
+
include_examples "config document replace CONF test"
|
203
|
+
end
|
204
|
+
|
205
|
+
context "set a new value in JSON" do
|
206
|
+
let (:final_text) { "{\n\t\"a\":\"b\",\n\t\"c\":\"d\",\n\t\"e\" : \"f\"\n}" }
|
207
|
+
include_examples "config document replace JSON test"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context "config document set new value no braces" do
|
212
|
+
let (:orig_text) { "\"a\":\"b\",\n\"c\":\"d\"\n" }
|
213
|
+
let (:final_text) { "\"a\":\"b\",\n\"c\":\"d\"\n\"e\" : \"f\"\n" }
|
214
|
+
let (:new_value) { "\"f\"" }
|
215
|
+
let (:replace_path) { "\"e\"" }
|
216
|
+
|
217
|
+
include_examples "config document replace CONF test"
|
218
|
+
end
|
219
|
+
|
220
|
+
context "config document set new value multi level CONF" do
|
221
|
+
let (:orig_text) { "a:b\nc:d" }
|
222
|
+
let (:final_text) { "a:b\nc:d\ne : {\n f : {\n g : 12\n }\n}" }
|
223
|
+
let (:new_value) { "12" }
|
224
|
+
let (:replace_path) { "e.f.g" }
|
225
|
+
|
226
|
+
include_examples "config document replace CONF test"
|
227
|
+
end
|
228
|
+
|
229
|
+
context "config document set new value multi level JSON" do
|
230
|
+
let (:orig_text) { "{\"a\":\"b\",\n\"c\":\"d\"}" }
|
231
|
+
let (:final_text) { "{\"a\":\"b\",\n\"c\":\"d\",\n \"e\" : {\n \"f\" : {\n \"g\" : 12\n }\n }}" }
|
232
|
+
let (:new_value) { "12" }
|
233
|
+
let (:replace_path) { "e.f.g" }
|
234
|
+
|
235
|
+
include_examples "config document replace JSON test"
|
236
|
+
end
|
237
|
+
|
238
|
+
context "config document set new config value" do
|
239
|
+
let (:orig_text) { "{\"a\": \"b\"}" }
|
240
|
+
let (:final_text) { "{\"a\": 12}" }
|
241
|
+
let (:config_doc_hocon) { ConfigDocumentFactory.parse_string(orig_text) }
|
242
|
+
let (:config_doc_json) { ConfigDocumentFactory.parse_string(orig_text, ConfigParseOptions.defaults.set_syntax(ConfigSyntax::JSON)) }
|
243
|
+
let (:new_value) { ConfigValueFactory.from_any_ref(12) }
|
244
|
+
|
245
|
+
it "should successfuly render the original text from both documents" do
|
246
|
+
expect(config_doc_hocon.render).to eq(orig_text)
|
247
|
+
expect(config_doc_json.render).to eq(orig_text)
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should succesfully set a new value on both documents" do
|
251
|
+
expect(config_doc_hocon.set_config_value("a", new_value).render).to eq(final_text)
|
252
|
+
expect(config_doc_json.set_config_value("a", new_value).render).to eq(final_text)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "config document has value" do
|
257
|
+
let (:orig_text) { "{a: b, a.b.c.d: e, c: {a: {b: c}}}" }
|
258
|
+
let (:config_doc) { ConfigDocumentFactory.parse_string(orig_text) }
|
259
|
+
|
260
|
+
it "should return true on paths that exist in the document" do
|
261
|
+
expect(config_doc.has_value?("a")).to be_truthy
|
262
|
+
expect(config_doc.has_value?("a.b.c")).to be_truthy
|
263
|
+
expect(config_doc.has_value?("c.a.b")).to be_truthy
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should return false on paths that don't exist in the document" do
|
267
|
+
expect(config_doc.has_value?("c.a.b.c")).to be_falsey
|
268
|
+
expect(config_doc.has_value?("a.b.c.d.e")).to be_falsey
|
269
|
+
expect(config_doc.has_value?("this.does.not.exist")).to be_falsey
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
context "config document remove value" do
|
274
|
+
let (:orig_text) { "{a: b, a.b.c.d: e, c: {a: {b: c}}}" }
|
275
|
+
let (:config_doc) { ConfigDocumentFactory.parse_string(orig_text) }
|
276
|
+
|
277
|
+
it "should remove a top-level setting with a simple value" do
|
278
|
+
expect(config_doc.remove_value("a").render).to eq("{c: {a: {b: c}}}")
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should remove a top-level setting with a complex value" do
|
282
|
+
expect(config_doc.remove_value("c").render).to eq("{a: b, a.b.c.d: e, }")
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should do nothing if the setting does not exist" do
|
286
|
+
expect(config_doc.remove_value("this.does.not.exist")).to eq(config_doc)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "config document remove value JSON" do
|
291
|
+
it "should not leave a trailing comma when removing a value in JSON" do
|
292
|
+
orig_text = '{"a": "b", "c": "d"}'
|
293
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text, ConfigParseOptions.defaults.set_syntax(ConfigSyntax::JSON))
|
294
|
+
expect(config_doc.remove_value("c").render).to eq('{"a": "b" }')
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context "config document remove multiple" do
|
299
|
+
it "should remove duplicate nested keys" do
|
300
|
+
orig_text = "a { b: 42 }, a.b = 43, a { b: { c: 44 } }"
|
301
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text)
|
302
|
+
removed = config_doc.remove_value("a.b")
|
303
|
+
expect(removed.render).to eq("a { }, a { }")
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context "config document remove overridden" do
|
308
|
+
it "should remove all instances of keys even if overridden by a top-level key/value pair" do
|
309
|
+
orig_text = "a { b: 42 }, a.b = 43, a { b: { c: 44 } }, a : 57 "
|
310
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text)
|
311
|
+
removed = config_doc.remove_value("a.b")
|
312
|
+
expect(removed.render).to eq("a { }, a { }, a : 57 ")
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context "config document remove nested" do
|
317
|
+
it "should remove nested keys if specified" do
|
318
|
+
orig_text = "a { b: 42 }, a.b = 43, a { b: { c: 44 } }"
|
319
|
+
config_doc = ConfigDocumentFactory.parse_string(orig_text)
|
320
|
+
removed = config_doc.remove_value("a.b.c")
|
321
|
+
expect(removed.render).to eq("a { b: 42 }, a.b = 43, a { b: { } }")
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
context "config document array failures" do
|
326
|
+
let (:orig_text) { "[1, 2, 3, 4, 5]" }
|
327
|
+
let (:document) { ConfigDocumentFactory.parse_string(orig_text) }
|
328
|
+
|
329
|
+
it "should throw when set_value is called and there is an array at the root" do
|
330
|
+
e = TestUtils.intercept(Hocon::ConfigError) { document.set_value("a", "1") }
|
331
|
+
expect(e.message).to include("ConfigDocument had an array at the root level")
|
332
|
+
end
|
333
|
+
|
334
|
+
it "should throw when has_value is called and there is an array at the root" do
|
335
|
+
e = TestUtils.intercept(Hocon::ConfigError) { document.has_value?("a") }
|
336
|
+
expect(e.message).to include("ConfigDocument had an array at the root level")
|
337
|
+
end
|
338
|
+
|
339
|
+
it "should throw when remove_value is called and there is an array at the root" do
|
340
|
+
e = TestUtils.intercept(Hocon::ConfigError) { document.remove_value("a") }
|
341
|
+
expect(e.message).to include("ConfigDocument had an array at the root level")
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
context "config document JSON replace failure" do
|
346
|
+
it "should fail when trying to replace with a value using HOCON syntax in JSON" do
|
347
|
+
orig_text = "{\"foo\": \"bar\", \"baz\": \"qux\"}"
|
348
|
+
document = ConfigDocumentFactory.parse_string(orig_text, ConfigParseOptions.defaults.set_syntax(ConfigSyntax::JSON))
|
349
|
+
|
350
|
+
e = TestUtils.intercept(Hocon::ConfigError) { document.set_value("foo", "unquoted") }
|
351
|
+
expect(e.message).to include("Token not allowed in valid JSON")
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
context "config document JSON replace with concatenation failure" do
|
356
|
+
it "should fail when trying to add a concatenation into a JSON document" do
|
357
|
+
orig_text = "{\"foo\": \"bar\", \"baz\": \"qux\"}"
|
358
|
+
document = ConfigDocumentFactory.parse_string(orig_text, ConfigParseOptions.defaults.set_syntax(ConfigSyntax::JSON))
|
359
|
+
|
360
|
+
e = TestUtils.intercept(Hocon::ConfigError) { document.set_value("foo", "1 2 3 concatenation") }
|
361
|
+
expect(e.message).to include("Parsing JSON and the value set in setValue was either a concatenation or had trailing whitespace, newlines, or comments")
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
context "config document file parse" do
|
366
|
+
let (:config_document) { ConfigDocumentFactory.parse_file(TestUtils.resource_file("test01.conf")) }
|
367
|
+
let (:file_text) {
|
368
|
+
file = File.open(TestUtils.resource_file("test01.conf"), "rb")
|
369
|
+
contents = file.read
|
370
|
+
file.close
|
371
|
+
contents
|
372
|
+
}
|
373
|
+
|
374
|
+
it "should correctly parse from a file" do
|
375
|
+
expect(config_document.render).to eq(file_text)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
# skipping reader parsing, since we don't support that in ruby hocon
|
380
|
+
|
381
|
+
context "config document indentation single line object" do
|
382
|
+
it "should properly indent a value in a single-line map" do
|
383
|
+
orig_text = "a { b: c }"
|
384
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
385
|
+
expect(config_document.set_value("a.d", "e").render).to eq("a { b: c, d : e }")
|
386
|
+
end
|
387
|
+
|
388
|
+
it "should properly indent a value in the top-level when it is on a single line" do
|
389
|
+
orig_text = "a { b: c }, d: e"
|
390
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
391
|
+
expect(config_document.set_value("f", "g").render).to eq("a { b: c }, d: e, f : g")
|
392
|
+
end
|
393
|
+
|
394
|
+
it "should not preserve trailing commas" do
|
395
|
+
orig_text = "a { b: c }, d: e,"
|
396
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
397
|
+
expect(config_document.set_value("f", "g").render).to eq("a { b: c }, d: e, f : g")
|
398
|
+
end
|
399
|
+
|
400
|
+
it "should add necessary keys along the path to the value and properly space them" do
|
401
|
+
orig_text = "a { b: c }, d: e,"
|
402
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
403
|
+
expect(config_document.set_value("f.g.h", "i").render).to eq("a { b: c }, d: e, f : { g : { h : i } }")
|
404
|
+
end
|
405
|
+
|
406
|
+
it "should properly indent keys added to the top-level with curly braces" do
|
407
|
+
orig_text = "{a { b: c }, d: e}"
|
408
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
409
|
+
expect(config_document.set_value("f", "g").render).to eq("{a { b: c }, d: e, f : g}")
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should add necessary keys along the path to the value and properly space them when the root has braces" do
|
413
|
+
orig_text = "{a { b: c }, d: e}"
|
414
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
415
|
+
expect(config_document.set_value("f.g.h", "i").render).to eq("{a { b: c }, d: e, f : { g : { h : i } }}")
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
context "config document indentation multi line object" do
|
420
|
+
context "document with no trailing newlines" do
|
421
|
+
let (:orig_text) { "a {\n b: c\n}" }
|
422
|
+
let (:config_document) { ConfigDocumentFactory.parse_string(orig_text) }
|
423
|
+
|
424
|
+
it "should properly indent a value in a multi-line map" do
|
425
|
+
expect(config_document.set_value("a.e", "f").render).to eq("a {\n b: c\n e : f\n}")
|
426
|
+
end
|
427
|
+
|
428
|
+
it "should properly add/indent any necessary objects along the way to the value" do
|
429
|
+
expect(config_document.set_value("a.d.e.f", "g").render).to eq("a {\n b: c\n d : {\n e : {\n f : g\n }\n }\n}")
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
context "document with multi-line root" do
|
434
|
+
let (:orig_text) { "a {\n b: c\n}\n" }
|
435
|
+
let (:config_document) { ConfigDocumentFactory.parse_string(orig_text) }
|
436
|
+
|
437
|
+
it "should properly indent a value at the root with multiple lines" do
|
438
|
+
expect(config_document.set_value("d", "e").render).to eq("a {\n b: c\n}\nd : e\n")
|
439
|
+
end
|
440
|
+
|
441
|
+
it "should properly add/indent any necessary objects along the way to the value" do
|
442
|
+
expect(config_document.set_value("d.e.f", "g").render).to eq("a {\n b: c\n}\nd : {\n e : {\n f : g\n }\n}\n")
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
context "config document indentation nested" do
|
448
|
+
it "should properly space a new key/value pair in a nested map in a single-line document" do
|
449
|
+
orig_text = "a { b { c { d: e } } }"
|
450
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
451
|
+
expect(config_document.set_value("a.b.c.f", "g").render).to eq("a { b { c { d: e, f : g } } }")
|
452
|
+
end
|
453
|
+
|
454
|
+
it "should properly space a new key/value pair in a nested map in a multi-line document" do
|
455
|
+
orig_text = "a {\n b {\n c {\n d: e\n }\n }\n}"
|
456
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
457
|
+
expect(config_document.set_value("a.b.c.f", "g").render).to eq("a {\n b {\n c {\n d: e\n f : g\n }\n }\n}")
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
context "config document indentation empty object" do
|
462
|
+
it "should properly space a new key/value pair in a single-line empty object" do
|
463
|
+
orig_text = "a { }"
|
464
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
465
|
+
expect(config_document.set_value("a.b", "c").render).to eq("a { b : c }")
|
466
|
+
end
|
467
|
+
|
468
|
+
it "should properly indent a new key/value pair in a multi-line empty object" do
|
469
|
+
orig_text = "a {\n b {\n }\n}"
|
470
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
471
|
+
expect(config_document.set_value("a.b.c", "d").render).to eq("a {\n b {\n c : d\n }\n}")
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context "config document indentation multi line value" do
|
476
|
+
let (:orig_text) { "a {\n b {\n c {\n d: e\n }\n }\n}" }
|
477
|
+
let (:config_document) { ConfigDocumentFactory.parse_string(orig_text) }
|
478
|
+
|
479
|
+
it "should successfully insert and indent a multi-line object" do
|
480
|
+
expect(config_document.set_value("a.b.c.f", "{\n g: h\n i: j\n k: {\n l: m\n }\n}").render
|
481
|
+
).to eq("a {\n b {\n c {\n d: e\n f : {\n g: h\n i: j\n k: {\n l: m\n }\n }\n }\n }\n}")
|
482
|
+
end
|
483
|
+
|
484
|
+
it "should successfully insert a concatenation with a multi-line array" do
|
485
|
+
expect(config_document.set_value("a.b.c.f", "12 13 [1,\n2,\n3,\n{\n a:b\n}]").render
|
486
|
+
).to eq("a {\n b {\n c {\n d: e\n f : 12 13 [1,\n 2,\n 3,\n {\n a:b\n }]\n }\n }\n}")
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context "config document indentation multi line value single line object" do
|
491
|
+
it "should get weird indentation when adding a multi-line value to a single-line object" do
|
492
|
+
orig_text = "a { b { } }"
|
493
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
494
|
+
expect(config_document.set_value("a.b.c", "{\n c:d\n}").render).to eq("a { b { c : {\n c:d\n } } }")
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
context "config document indentation single line object containing multi line value" do
|
499
|
+
it "should treat an object with no new-lines outside of its values as a single-line object" do
|
500
|
+
orig_text = "a { b {\n c: d\n} }"
|
501
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
502
|
+
expect(config_document.set_value("a.e", "f").render).to eq("a { b {\n c: d\n}, e : f }")
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
context "config document indentation replacing with multi line value" do
|
507
|
+
it "should properly indent a multi-line value when replacing a single-line value" do
|
508
|
+
orig_text = "a {\n b {\n c : 22\n }\n}"
|
509
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
510
|
+
expect(config_document.set_value("a.b.c", "{\n d:e\n}").render).to eq("a {\n b {\n c : {\n d:e\n }\n }\n}")
|
511
|
+
end
|
512
|
+
|
513
|
+
it "should properly indent a multi-line value when replacing a single-line value in an object with multiple keys" do
|
514
|
+
orig_text = "a {\n b {\n f : 10\n c : 22\n }\n}"
|
515
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
516
|
+
expect(config_document.set_value("a.b.c", "{\n d:e\n}").render).to eq("a {\n b {\n f : 10\n c : {\n d:e\n }\n }\n}")
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
context "config document indentation value with include" do
|
521
|
+
it "should indent an include node" do
|
522
|
+
orig_text = "a {\n b {\n c : 22\n }\n}"
|
523
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
524
|
+
expect(config_document.set_value("a.b.d", "{\n include \"foo\"\n e:f\n}").render
|
525
|
+
).to eq("a {\n b {\n c : 22\n d : {\n include \"foo\"\n e:f\n }\n }\n}")
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
context "config document indentation based on include node" do
|
530
|
+
it "should indent properly when only an include node is present in the object in which the value is inserted" do
|
531
|
+
orig_text = "a : b\n include \"foo\"\n"
|
532
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
533
|
+
expect(config_document.set_value("c", "d").render).to eq("a : b\n include \"foo\"\n c : d\n")
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
context "insertion into an empty document" do
|
538
|
+
it "should successfully insert a value into an empty document" do
|
539
|
+
orig_text = ""
|
540
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
541
|
+
expect(config_document.set_value("a", "1").render).to eq("a : 1")
|
542
|
+
end
|
543
|
+
|
544
|
+
it "should successfully insert a multi-line object into an empty document" do
|
545
|
+
orig_text = ""
|
546
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
547
|
+
expect(config_document.set_value("a.b", "1").render).to eq("a : {\n b : 1\n}")
|
548
|
+
end
|
549
|
+
|
550
|
+
it "should successfully insert a hash into an empty document" do
|
551
|
+
orig_text = ""
|
552
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
553
|
+
map_val = ConfigValueFactory.from_any_ref({"a" => 1, "b" => 2})
|
554
|
+
|
555
|
+
expect(config_document.set_config_value("a", map_val).render).to eq("a : {\n \"a\" : 1,\n \"b\" : 2\n}")
|
556
|
+
end
|
557
|
+
|
558
|
+
it "should successfully insert an array into an empty document" do
|
559
|
+
orig_text = ""
|
560
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
561
|
+
array_val = ConfigValueFactory.from_any_ref([1,2])
|
562
|
+
|
563
|
+
expect(config_document.set_config_value("a", array_val).render).to eq("a : [\n 1,\n 2\n]")
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
context "can insert a map parsed with ConfigValueFactory" do
|
568
|
+
it "should successfully insert a map into a document" do
|
569
|
+
orig_text = "{ a : b }"
|
570
|
+
config_document = ConfigDocumentFactory.parse_string(orig_text)
|
571
|
+
|
572
|
+
map = ConfigValueFactory.from_any_ref({"a" => 1, "b" => 2})
|
573
|
+
expect(config_document.set_config_value("a", map).render).to eq("{ a : {\n \"a\" : 1,\n \"b\" : 2\n } }")
|
574
|
+
end
|
575
|
+
end
|
576
|
+
end
|