i18n_flow 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +13 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +45 -0
  8. data/LICENSE +22 -0
  9. data/README.md +103 -0
  10. data/Rakefile +2 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/doc/rules.md +316 -0
  14. data/doc/tags.md +488 -0
  15. data/example/example.en.yml +14 -0
  16. data/example/example.ja.yml +9 -0
  17. data/exe/i18n_flow +11 -0
  18. data/i18n_flow.gemspec +28 -0
  19. data/i18n_flow.yml +8 -0
  20. data/lib/i18n_flow/cli/color.rb +18 -0
  21. data/lib/i18n_flow/cli/command_base.rb +33 -0
  22. data/lib/i18n_flow/cli/copy_command.rb +69 -0
  23. data/lib/i18n_flow/cli/help_command.rb +29 -0
  24. data/lib/i18n_flow/cli/lint_command/ascii.erb +45 -0
  25. data/lib/i18n_flow/cli/lint_command/ascii_renderer.rb +58 -0
  26. data/lib/i18n_flow/cli/lint_command/markdown.erb +49 -0
  27. data/lib/i18n_flow/cli/lint_command/markdown_renderer.rb +55 -0
  28. data/lib/i18n_flow/cli/lint_command.rb +55 -0
  29. data/lib/i18n_flow/cli/read_config_command.rb +20 -0
  30. data/lib/i18n_flow/cli/search_command/default.erb +11 -0
  31. data/lib/i18n_flow/cli/search_command/default_renderer.rb +67 -0
  32. data/lib/i18n_flow/cli/search_command/oneline.erb +5 -0
  33. data/lib/i18n_flow/cli/search_command/oneline_renderer.rb +39 -0
  34. data/lib/i18n_flow/cli/search_command.rb +59 -0
  35. data/lib/i18n_flow/cli/split_command.rb +20 -0
  36. data/lib/i18n_flow/cli/version_command.rb +9 -0
  37. data/lib/i18n_flow/cli.rb +42 -0
  38. data/lib/i18n_flow/configuration.rb +205 -0
  39. data/lib/i18n_flow/parser.rb +34 -0
  40. data/lib/i18n_flow/repository.rb +39 -0
  41. data/lib/i18n_flow/search.rb +176 -0
  42. data/lib/i18n_flow/splitter/merger.rb +60 -0
  43. data/lib/i18n_flow/splitter/strategy.rb +66 -0
  44. data/lib/i18n_flow/splitter.rb +5 -0
  45. data/lib/i18n_flow/util.rb +57 -0
  46. data/lib/i18n_flow/validator/errors.rb +99 -0
  47. data/lib/i18n_flow/validator/file_scope.rb +58 -0
  48. data/lib/i18n_flow/validator/multiplexer.rb +58 -0
  49. data/lib/i18n_flow/validator/symmetry.rb +154 -0
  50. data/lib/i18n_flow/validator.rb +4 -0
  51. data/lib/i18n_flow/version.rb +7 -0
  52. data/lib/i18n_flow/yaml_ast_proxy/mapping.rb +72 -0
  53. data/lib/i18n_flow/yaml_ast_proxy/node.rb +128 -0
  54. data/lib/i18n_flow/yaml_ast_proxy/node_meta_data.rb +86 -0
  55. data/lib/i18n_flow/yaml_ast_proxy/sequence.rb +29 -0
  56. data/lib/i18n_flow/yaml_ast_proxy.rb +57 -0
  57. data/lib/i18n_flow.rb +15 -0
  58. data/spec/lib/i18n_flow/cli/command_base_spec.rb +46 -0
  59. data/spec/lib/i18n_flow/cli/help_command_spec.rb +13 -0
  60. data/spec/lib/i18n_flow/cli/version_command_spec.rb +13 -0
  61. data/spec/lib/i18n_flow/configuration_spec.rb +334 -0
  62. data/spec/lib/i18n_flow/repository_spec.rb +40 -0
  63. data/spec/lib/i18n_flow/splitter/merger_spec.rb +149 -0
  64. data/spec/lib/i18n_flow/util_spec.rb +194 -0
  65. data/spec/lib/i18n_flow/validator/file_scope_spec.rb +74 -0
  66. data/spec/lib/i18n_flow/validator/multiplexer_spec.rb +68 -0
  67. data/spec/lib/i18n_flow/validator/symmetry_spec.rb +511 -0
  68. data/spec/lib/i18n_flow/yaml_ast_proxy/node_spec.rb +151 -0
  69. data/spec/lib/i18n_flow_spec.rb +21 -0
  70. data/spec/spec_helper.rb +16 -0
  71. data/spec/support/repository_examples.rb +60 -0
  72. data/spec/support/util_macro.rb +14 -0
  73. metadata +214 -0
@@ -0,0 +1,57 @@
1
+ require 'psych'
2
+ require_relative 'yaml_ast_proxy/node'
3
+ require_relative 'yaml_ast_proxy/mapping'
4
+ require_relative 'yaml_ast_proxy/sequence'
5
+
6
+ module I18nFlow::YamlAstProxy
7
+ def self.create(node, parent: nil, scopes: [], file_path: nil)
8
+ case node
9
+ when NilClass
10
+ nil
11
+ when Node
12
+ if node.parent == parent \
13
+ && node.scopes == scopes \
14
+ && node.file_path == file_path
15
+ node
16
+ else
17
+ node.class.new(node.node,
18
+ parent: parent,
19
+ scopes: scopes,
20
+ file_path: file_path,
21
+ )
22
+ end
23
+ when Psych::Nodes::Stream, Psych::Nodes::Document
24
+ Node.new(node.children.first,
25
+ parent: node,
26
+ scopes: scopes,
27
+ file_path: file_path,
28
+ )
29
+ when Psych::Nodes::Mapping
30
+ Mapping.new(node,
31
+ parent: parent,
32
+ scopes: scopes,
33
+ file_path: file_path,
34
+ )
35
+ when Psych::Nodes::Sequence
36
+ Sequence.new(node,
37
+ parent: parent,
38
+ scopes: scopes,
39
+ file_path: file_path,
40
+ )
41
+ else
42
+ Node.new(node,
43
+ parent: parent,
44
+ scopes: scopes,
45
+ file_path: file_path,
46
+ )
47
+ end
48
+ end
49
+
50
+ def self.new_root
51
+ doc = Psych::Nodes::Document.new([], [], true)
52
+ doc.children << Psych::Nodes::Mapping.new
53
+ stream = Psych::Nodes::Stream.new
54
+ stream.children << doc
55
+ create(stream)
56
+ end
57
+ end
data/lib/i18n_flow.rb ADDED
@@ -0,0 +1,15 @@
1
+ module I18nFlow
2
+ extend self
3
+
4
+ def config
5
+ @config ||= Configuration.new
6
+ end
7
+
8
+ def configure(&block)
9
+ config.update(&block)
10
+ end
11
+ end
12
+
13
+ require_relative 'i18n_flow/version'
14
+ require_relative 'i18n_flow/configuration'
15
+ require_relative 'i18n_flow/validator'
@@ -0,0 +1,46 @@
1
+ require 'i18n_flow/cli/command_base'
2
+
3
+ describe I18nFlow::CLI::CommandBase do
4
+ let(:command) { I18nFlow::CLI::CommandBase.new([]) }
5
+
6
+ describe '#invoke!' do
7
+ it 'should raise a not implemented error' do
8
+ expect {
9
+ command.invoke!
10
+ }.to raise_error(/implemented/)
11
+ end
12
+ end
13
+
14
+ describe '#exit_with_message' do
15
+ let(:message) { 'a message' }
16
+ let(:message_regexp) { /a message/ }
17
+
18
+ context 'With status code of zero' do
19
+ let(:status) { 0 }
20
+
21
+ it 'should print a message to stdout and exit' do
22
+ expect {
23
+ begin
24
+ command.exit_with_message(status, message)
25
+ rescue SystemExit => e
26
+ expect(e.status).to eq(status)
27
+ end
28
+ }.to output(message_regexp).to_stdout
29
+ end
30
+ end
31
+
32
+ context 'With status code of non-zero' do
33
+ let(:status) { 1 }
34
+
35
+ it 'should print a message to stderr and exit' do
36
+ expect {
37
+ begin
38
+ command.exit_with_message(status, message)
39
+ rescue SystemExit => e
40
+ expect(e.status).to eq(status)
41
+ end
42
+ }.to output(message_regexp).to_stderr
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ require 'i18n_flow/cli/help_command'
2
+
3
+ describe I18nFlow::CLI::HelpCommand do
4
+ let(:command) { I18nFlow::CLI::HelpCommand.new([]) }
5
+
6
+ describe '#invoke!' do
7
+ it 'should print help' do
8
+ expect {
9
+ command.invoke!
10
+ }.to output(/Usage/).to_stdout
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'i18n_flow/cli/version_command'
2
+
3
+ describe I18nFlow::CLI::VersionCommand do
4
+ let(:command) { I18nFlow::CLI::VersionCommand.new([]) }
5
+
6
+ describe '#invoke!' do
7
+ it 'should print gem version' do
8
+ expect {
9
+ command.invoke!
10
+ }.to output(/v\d+\.\d+.\d+/).to_stdout
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,334 @@
1
+ require 'i18n_flow/configuration'
2
+
3
+ describe I18nFlow::Configuration do
4
+ let(:configuration) { I18nFlow::Configuration.new }
5
+
6
+ describe '.new' do
7
+ let(:options) do
8
+ %i[
9
+ base_path
10
+ glob_patterns
11
+ valid_locales
12
+ locale_pairs
13
+ split_max_level
14
+ split_line_threshold
15
+ ]
16
+ end
17
+
18
+ it 'should set default values' do
19
+ options.each do |option|
20
+ expect(configuration.respond_to?(option)).to be(true)
21
+ expect(configuration.send(option)).not_to be_nil
22
+ end
23
+ end
24
+ end
25
+
26
+ describe '#base_path, #base_path=' do
27
+ it 'should return an instance of Pathname' do
28
+ expect(configuration.base_path).to be_a(Pathname)
29
+ end
30
+
31
+ it 'should store an instance of Pathname from a string in the setter' do
32
+ path = 'foo/bar'
33
+
34
+ expect {
35
+ configuration.base_path = path
36
+ }.not_to raise_error
37
+
38
+ expect(configuration.base_path).to be_a(Pathname)
39
+ expect(configuration.base_path.to_s).to eq(path)
40
+ end
41
+ end
42
+
43
+ describe '#glob_patterns, #glob_patterns=' do
44
+ it 'should return an array' do
45
+ expect(configuration.glob_patterns).to be_a(Array)
46
+ end
47
+
48
+ it 'should store the given value as an array of strings in the setter' do
49
+ expect {
50
+ configuration.glob_patterns = [:'foo.yml']
51
+ }.not_to raise_error
52
+
53
+ expect(configuration.glob_patterns).to eq(['foo.yml'])
54
+ end
55
+ end
56
+
57
+ describe '#valid_locales, #valid_locales=' do
58
+ it 'should return an array' do
59
+ expect(configuration.valid_locales).to be_a(Array)
60
+ end
61
+
62
+ it 'should store the given value as an array of strings in the setter' do
63
+ expect {
64
+ configuration.valid_locales = [:en]
65
+ }.not_to raise_error
66
+
67
+ expect(configuration.valid_locales).to eq(['en'])
68
+ end
69
+ end
70
+
71
+ describe '#locale_pairs, #locale_pairs=' do
72
+ it 'should return an array' do
73
+ expect(configuration.locale_pairs).to be_a(Array)
74
+ end
75
+
76
+ it 'should store the given value as an array of strings in the setter' do
77
+ expect {
78
+ configuration.locale_pairs = [[:en, :ja]]
79
+ }.not_to raise_error
80
+
81
+ expect(configuration.locale_pairs).to eq([['en', 'ja']])
82
+ end
83
+ end
84
+
85
+ describe '#linters, #linters=' do
86
+ it 'should return an array' do
87
+ expect(configuration.linters).to be_a(Array)
88
+ end
89
+
90
+ it 'should store the given value as an array of symbols in the setter' do
91
+ expect {
92
+ configuration.linters = ['foo', 'bar']
93
+ }.not_to raise_error
94
+
95
+ expect(configuration.linters).to eq([:foo, :bar])
96
+ end
97
+ end
98
+
99
+ describe '#validate!' do
100
+ context 'base_path' do
101
+ it 'should raise an error if it is a relative path' do
102
+ configuration.base_path = 'relative/path'
103
+
104
+ expect {
105
+ configuration.validate!
106
+ }.to raise_error(/base_path/)
107
+ end
108
+
109
+ it 'should not raise if it is a absolute path' do
110
+ configuration.base_path = '/absolute/path'
111
+
112
+ expect {
113
+ configuration.validate!
114
+ }.not_to raise_error
115
+ end
116
+ end
117
+
118
+ context 'glob_patterns' do
119
+ it 'should raise an error if it is not an array' do
120
+ configuration.glob_patterns = ''
121
+
122
+ expect {
123
+ configuration.validate!
124
+ }.to raise_error(/glob_patterns/)
125
+ end
126
+
127
+ it 'should raise an error if it is empty' do
128
+ configuration.glob_patterns = []
129
+
130
+ expect {
131
+ configuration.validate!
132
+ }.to raise_error(/glob_patterns/)
133
+ end
134
+
135
+ it 'should not raise if it is an array' do
136
+ configuration.glob_patterns = ['*.yml']
137
+
138
+ expect {
139
+ configuration.validate!
140
+ }.not_to raise_error
141
+ end
142
+ end
143
+
144
+ context 'locale_pairs' do
145
+ it 'should raise an error if it is blank' do
146
+ configuration.locale_pairs = ''
147
+
148
+ expect {
149
+ configuration.validate!
150
+ }.to raise_error(/locale_pairs/)
151
+ end
152
+
153
+ it 'should raise if it is not an array of pair' do
154
+ configuration.locale_pairs = [['en']]
155
+
156
+ expect {
157
+ configuration.validate!
158
+ }.to raise_error(/locale_pairs/)
159
+ end
160
+
161
+ it 'should not raise if it is an array' do
162
+ configuration.locale_pairs = [['en', 'ja']]
163
+
164
+ expect {
165
+ configuration.validate!
166
+ }.not_to raise_error
167
+ end
168
+ end
169
+
170
+ context 'linters' do
171
+ it 'should raise an error if it is blank' do
172
+ configuration.linters = ''
173
+
174
+ expect {
175
+ configuration.validate!
176
+ }.to raise_error(/linters/)
177
+ end
178
+
179
+ it 'should raise if the element contains invalid value' do
180
+ configuration.linters = [:foo]
181
+
182
+ expect {
183
+ configuration.validate!
184
+ }.to raise_error(/linters/)
185
+ end
186
+
187
+ it 'should not raise if it is valid' do
188
+ configuration.linters = [:file_scope]
189
+
190
+ expect {
191
+ configuration.validate!
192
+ }.not_to raise_error
193
+ end
194
+ end
195
+
196
+ context 'valid_locales' do
197
+ it 'should raise an error if it is not an array' do
198
+ configuration.valid_locales = ''
199
+
200
+ expect {
201
+ configuration.validate!
202
+ }.to raise_error(/valid_locales/)
203
+ end
204
+
205
+ it 'should raise an error if it is empty' do
206
+ configuration.valid_locales = []
207
+
208
+ expect {
209
+ configuration.validate!
210
+ }.to raise_error(/valid_locales/)
211
+ end
212
+
213
+ it 'should not raise if eligible' do
214
+ configuration.valid_locales = [:en]
215
+
216
+ expect {
217
+ configuration.validate!
218
+ }.not_to raise_error
219
+ end
220
+ end
221
+
222
+ context 'split_max_level' do
223
+ it 'should raise an error if it is not an integer' do
224
+ configuration.split_max_level = 'foo'
225
+
226
+ expect {
227
+ configuration.validate!
228
+ }.to raise_error(/split_max_level/)
229
+ end
230
+
231
+ it 'should not raise if it is an integer' do
232
+ configuration.split_max_level = 123
233
+
234
+ expect {
235
+ configuration.validate!
236
+ }.not_to raise_error
237
+ end
238
+ end
239
+
240
+ context 'split_line_threshold' do
241
+ it 'should raise an error if it is not an integer' do
242
+ configuration.split_line_threshold = 'foo'
243
+
244
+ expect {
245
+ configuration.validate!
246
+ }.to raise_error(/split_line_threshold/)
247
+ end
248
+
249
+ it 'should not raise if it is an integer' do
250
+ configuration.split_line_threshold = 123
251
+
252
+ expect {
253
+ configuration.validate!
254
+ }.not_to raise_error
255
+ end
256
+ end
257
+ end
258
+
259
+ context 'auto config' do
260
+ describe '#auto_configure!' do
261
+ it 'should call `load_from_file!` and `update`' do
262
+ allow(configuration).to receive(:load_from_file!).and_return(true)
263
+ allow(configuration).to receive(:update).and_return(true)
264
+
265
+ expect(configuration).to receive(:load_from_file!).once.ordered
266
+ expect(configuration).to receive(:update).once.ordered
267
+
268
+ configuration.auto_configure!
269
+ end
270
+ end
271
+
272
+ describe '#load_from_file!' do
273
+ let(:pwd) { '/path/to/pwd' }
274
+ let(:yaml_file_path) { '/path/to/i18n_flow.yml' }
275
+
276
+ let(:yaml_file) do
277
+ FakeFS::FakeFile.new.tap do |f|
278
+ f.content = <<-YAML
279
+ glob_patterns:
280
+ - 'config/locales/**/*.yml'
281
+ locale_pairs:
282
+ - ['en', 'ja']
283
+ valid_locales:
284
+ - 'ja'
285
+ - 'en'
286
+ YAML
287
+ end
288
+ end
289
+
290
+ before do
291
+ FakeFS::FileSystem.add(pwd)
292
+ Dir.chdir(pwd)
293
+ end
294
+
295
+ it 'should raise an error if no file is found' do
296
+ expect {
297
+ configuration.send(:load_from_file!)
298
+ }.to raise_error(I18nFlow::Configuration::NoConfigurationFileFoundError)
299
+ end
300
+
301
+ it 'should set `base_path` to the directory of yaml file' do
302
+ FakeFS::FileSystem.add(yaml_file_path, yaml_file)
303
+
304
+ expect {
305
+ configuration.send(:load_from_file!)
306
+ }.not_to raise_error
307
+
308
+ expect(configuration.base_path).to eq(Pathname.new(File.dirname(yaml_file_path)))
309
+ end
310
+
311
+ it 'should set other option values from yaml' do
312
+ FakeFS::FileSystem.add(yaml_file_path, yaml_file)
313
+
314
+ expect {
315
+ configuration.send(:load_from_file!)
316
+ }.not_to raise_error
317
+
318
+ expect(configuration.locale_pairs).to eq([['en', 'ja']])
319
+ expect(configuration.valid_locales).to eq(['ja', 'en'])
320
+ end
321
+
322
+ it 'should raise an error if there is invalid option in yaml' do
323
+ FakeFS::FileSystem.add(yaml_file_path, yaml_file)
324
+ yaml_file.content = <<-YAML
325
+ foo: true
326
+ YAML
327
+
328
+ expect {
329
+ configuration.send(:load_from_file!)
330
+ }.to raise_error(KeyError, /foo/)
331
+ end
332
+ end
333
+ end
334
+ end
@@ -0,0 +1,40 @@
1
+ require 'i18n_flow/repository'
2
+
3
+ describe I18nFlow::Repository do
4
+ include_examples :create_repository
5
+
6
+ describe '#file_paths' do
7
+ it 'should return an array of matched file paths' do
8
+ expect(repository.file_paths).to match_array([
9
+ '/fixtures/models/user.en.yml',
10
+ '/fixtures/models/user.ja.yml',
11
+ '/fixtures/views/profiles/show.en.yml',
12
+ '/fixtures/views/profiles/show.ja.yml',
13
+ '/fixtures/views/profiles/show.fr.yml',
14
+ ])
15
+ end
16
+ end
17
+
18
+ describe '#asts_by_path' do
19
+ it 'should return a hash of tree indexed by (relative) file paths' do
20
+ expect(repository.asts_by_path.keys).to match_array([
21
+ 'models/user.en.yml',
22
+ 'models/user.ja.yml',
23
+ 'views/profiles/show.en.yml',
24
+ 'views/profiles/show.ja.yml',
25
+ 'views/profiles/show.fr.yml',
26
+ ])
27
+ end
28
+ end
29
+
30
+ describe '#asts_by_scope' do
31
+ it 'should return a hash of tree indexed by scopes' do
32
+ expect(repository.asts_by_scope.keys).to match_array([
33
+ 'models.user',
34
+ 'views.profiles.show',
35
+ ])
36
+ expect(repository.asts_by_scope['models.user'].keys).to match_array(['en', 'ja'])
37
+ expect(repository.asts_by_scope['views.profiles.show'].keys).to match_array(['en', 'ja', 'fr'])
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,149 @@
1
+ require 'i18n_flow/splitter/merger'
2
+
3
+ describe I18nFlow::Splitter::Merger do
4
+ let(:merger) { I18nFlow::Splitter::Merger.new([]) }
5
+
6
+ describe '#perform_merge!' do
7
+ it 'should append root chunks' do
8
+ ast_1 = parse_yaml(<<-YAML)
9
+ en:
10
+ map:
11
+ foo_1: 'foo_1'
12
+ bar_1: 'bar_1'
13
+ YAML
14
+ result = parse_yaml(<<-YAML)
15
+ en:
16
+ map:
17
+ foo_1: 'foo_1'
18
+ bar_1: 'bar_1'
19
+ YAML
20
+
21
+ allow(merger).to receive(:chunks).and_return([
22
+ ast_1,
23
+ ])
24
+
25
+ merger.perform_merge!
26
+
27
+ expect(merger.to_yaml).to eq(result.to_yaml)
28
+ end
29
+
30
+ it 'should append partial chunks' do
31
+ ast_1 = parse_yaml(<<-YAML)
32
+ en:
33
+ map:
34
+ foo_1: 'foo_1'
35
+ bar_1: 'bar_1'
36
+ YAML
37
+ result = parse_yaml(<<-YAML)
38
+ en:
39
+ map:
40
+ foo_1: 'foo_1'
41
+ bar_1: 'bar_1'
42
+ YAML
43
+
44
+ allow(merger).to receive(:chunks).and_return([
45
+ ast_1['en']['map'],
46
+ ])
47
+
48
+ merger.perform_merge!
49
+
50
+ expect(merger.to_yaml).to eq(result.to_yaml)
51
+ end
52
+
53
+ it 'should merge root chunks' do
54
+ ast_1 = parse_yaml(<<-YAML)
55
+ en:
56
+ map:
57
+ foo_1: 'foo_1'
58
+ bar: 'bar_1'
59
+ YAML
60
+ ast_2 = parse_yaml(<<-YAML)
61
+ en:
62
+ map:
63
+ foo_2: 'foo_2'
64
+ bar: 'bar_2'
65
+ YAML
66
+ result = parse_yaml(<<-YAML)
67
+ en:
68
+ map:
69
+ foo_1: 'foo_1'
70
+ bar: 'bar_2'
71
+ foo_2: 'foo_2'
72
+ YAML
73
+
74
+ allow(merger).to receive(:chunks).and_return([
75
+ ast_1,
76
+ ast_2,
77
+ ])
78
+
79
+ merger.perform_merge!
80
+
81
+ expect(merger.to_yaml).to eq(result.to_yaml)
82
+ end
83
+
84
+ it 'should merge partial mapping chunks' do
85
+ ast_1 = parse_yaml(<<-YAML)
86
+ en:
87
+ map:
88
+ foo_1: 'foo_1'
89
+ bar: 'bar_1'
90
+ YAML
91
+ ast_2 = parse_yaml(<<-YAML)
92
+ en:
93
+ map:
94
+ foo_2: 'foo_2'
95
+ bar: 'bar_2'
96
+ YAML
97
+ result = parse_yaml(<<-YAML)
98
+ en:
99
+ map:
100
+ foo_1: 'foo_1'
101
+ bar: 'bar_2'
102
+ foo_2: 'foo_2'
103
+ YAML
104
+
105
+ allow(merger).to receive(:chunks).and_return([
106
+ ast_1['en']['map']['foo_1'],
107
+ ast_1['en']['map']['bar'],
108
+ ast_2['en']['map'],
109
+ ])
110
+
111
+ merger.perform_merge!
112
+
113
+ expect(merger.to_yaml).to eq(result.to_yaml)
114
+ end
115
+
116
+ it 'should merge partial sequence chunks' do
117
+ ast_1 = parse_yaml(<<-YAML)
118
+ en:
119
+ seq:
120
+ - 'seq_1_1'
121
+ - 'seq_1_2'
122
+ YAML
123
+ ast_2 = parse_yaml(<<-YAML)
124
+ en:
125
+ seq:
126
+ - 'seq_2_1'
127
+ - 'seq_2_2'
128
+ YAML
129
+ result = parse_yaml(<<-YAML)
130
+ en:
131
+ seq:
132
+ - 'seq_1_1'
133
+ - 'seq_1_2'
134
+ - 'seq_2_1'
135
+ - 'seq_2_2'
136
+ YAML
137
+
138
+ allow(merger).to receive(:chunks).and_return([
139
+ ast_1['en']['seq'][0],
140
+ ast_1['en']['seq'][1],
141
+ ast_2['en']['seq'],
142
+ ])
143
+
144
+ merger.perform_merge!
145
+
146
+ expect(merger.to_yaml).to eq(result.to_yaml)
147
+ end
148
+ end
149
+ end