twine 0.8.1 → 0.9.0

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.
data/lib/twine/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Twine
2
- VERSION = '0.8.1'
2
+ VERSION = '0.9.0'
3
3
  end
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,2 @@
1
+ Üß`
2
+ da
data/test/test_cli.rb CHANGED
@@ -211,7 +211,7 @@ class CLITestCase < TwineTestCase
211
211
 
212
212
  def test_default_options
213
213
  parse_with ''
214
- expected = {command: 'validate-strings-file', strings_file: 'input.txt', include: "all"}
214
+ expected = {command: 'validate-strings-file', strings_file: 'input.txt', include: :all}
215
215
  assert_equal expected, @options
216
216
  end
217
217
 
@@ -266,29 +266,17 @@ class CLITestCase < TwineTestCase
266
266
  end
267
267
 
268
268
  def test_format
269
- random_format = Twine::Formatters.formatters.sample.format_name
269
+ random_format = Twine::Formatters.formatters.sample.format_name.downcase
270
270
  parse_with "--format #{random_format}"
271
271
  assert_equal random_format, @options[:format]
272
272
  end
273
273
 
274
- def test_format_ignores_case
275
- random_format = Twine::Formatters.formatters.sample.format_name
276
- parse_with "--format #{random_format.upcase}"
277
- assert_equal random_format, @options[:format]
278
- end
279
-
280
274
  def test_include
281
- random_set = ['all', 'translated', 'untranslated'].sample
275
+ random_set = [:all, :translated, :untranslated].sample
282
276
  parse_with "--include #{random_set}"
283
277
  assert_equal random_set, @options[:include]
284
278
  end
285
279
 
286
- def test_include_ignores_case
287
- random_set = ['all', 'translated', 'untranslated'].sample
288
- parse_with "--include #{random_set.upcase}"
289
- assert_equal random_set, @options[:include]
290
- end
291
-
292
280
  def test_output_path
293
281
  parse_with "--output-file #{@output_path}"
294
282
  assert_equal @output_path, @options[:output_path]
@@ -5,7 +5,7 @@ class TestConsumeLocDrop < CommandTestCase
5
5
  super
6
6
 
7
7
  options = {}
8
- options[:input_path] = fixture 'consume_loc_drop.zip'
8
+ options[:input_path] = fixture_path 'consume_loc_drop.zip'
9
9
  options[:output_path] = @output_path
10
10
  options[:format] = 'apple'
11
11
 
@@ -14,31 +14,31 @@ class TestConsumeStringFile < CommandTestCase
14
14
  Twine::Runner.new(options, @strings)
15
15
  end
16
16
 
17
- def prepare_mock_read_file_formatter(formatter_class)
17
+ def prepare_mock_read_formatter(formatter_class)
18
18
  formatter = prepare_mock_formatter(formatter_class)
19
- formatter.expects(:read_file)
19
+ formatter.expects(:read)
20
20
  end
21
21
 
22
22
  def test_deducts_android_format_from_output_path
23
- prepare_mock_read_file_formatter Twine::Formatters::Android
23
+ prepare_mock_read_formatter Twine::Formatters::Android
24
24
 
25
25
  new_runner('fr', 'fr.xml').consume_string_file
26
26
  end
27
27
 
28
28
  def test_deducts_apple_format_from_output_path
29
- prepare_mock_read_file_formatter Twine::Formatters::Apple
29
+ prepare_mock_read_formatter Twine::Formatters::Apple
30
30
 
31
31
  new_runner('fr', 'fr.strings').consume_string_file
32
32
  end
33
33
 
34
34
  def test_deducts_jquery_format_from_output_path
35
- prepare_mock_read_file_formatter Twine::Formatters::JQuery
35
+ prepare_mock_read_formatter Twine::Formatters::JQuery
36
36
 
37
37
  new_runner('fr', 'fr.json').consume_string_file
38
38
  end
39
39
 
40
40
  def test_deducts_gettext_format_from_output_path
41
- prepare_mock_read_file_formatter Twine::Formatters::Gettext
41
+ prepare_mock_read_formatter Twine::Formatters::Gettext
42
42
 
43
43
  new_runner('fr', 'fr.po').consume_string_file
44
44
  end
@@ -46,8 +46,74 @@ class TestConsumeStringFile < CommandTestCase
46
46
  def test_deducts_language_from_input_path
47
47
  random_language = KNOWN_LANGUAGES.sample
48
48
  formatter = prepare_mock_formatter Twine::Formatters::Android
49
- formatter.expects(:read_file).with(anything, random_language)
49
+ formatter.expects(:read).with(anything, random_language)
50
50
 
51
51
  new_runner(nil, "#{random_language}.xml").consume_string_file
52
52
  end
53
+
54
+ class TestEncodings < CommandTestCase
55
+ class DummyFormatter < Twine::Formatters::Abstract
56
+ attr_reader :content
57
+
58
+ def extension
59
+ '.dummy'
60
+ end
61
+
62
+ def format_name
63
+ 'dummy'
64
+ end
65
+
66
+ def read(io, lang)
67
+ @content = io.read
68
+ end
69
+ end
70
+
71
+ def new_runner(input_path, encoding = nil)
72
+ options = {}
73
+ options[:output_path] = @output_path
74
+ options[:input_path] = input_path
75
+ options[:encoding] = encoding if encoding
76
+ options[:languages] = 'en'
77
+
78
+ @strings = Twine::StringsFile.new
79
+ @strings.language_codes.concat KNOWN_LANGUAGES
80
+
81
+ Twine::Runner.new(options, @strings)
82
+ end
83
+
84
+ def setup
85
+ super
86
+ @expected_content = "Üß`\nda\n"
87
+ end
88
+
89
+ def test_reads_utf8
90
+ formatter = prepare_mock_formatter DummyFormatter
91
+ new_runner(fixture_path('enc_utf8.dummy')).consume_string_file
92
+ assert_equal @expected_content, formatter.content
93
+ end
94
+
95
+ def test_reads_utf16le_bom
96
+ formatter = prepare_mock_formatter DummyFormatter
97
+ new_runner(fixture_path('enc_utf16le_bom.dummy')).consume_string_file
98
+ assert_equal @expected_content, formatter.content
99
+ end
100
+
101
+ def test_reads_utf16be_bom
102
+ formatter = prepare_mock_formatter DummyFormatter
103
+ new_runner(fixture_path('enc_utf16be_bom.dummy')).consume_string_file
104
+ assert_equal @expected_content, formatter.content
105
+ end
106
+
107
+ def test_reads_utf16le
108
+ formatter = prepare_mock_formatter DummyFormatter
109
+ new_runner(fixture_path('enc_utf16le.dummy'), 'UTF-16LE').consume_string_file
110
+ assert_equal @expected_content, formatter.content
111
+ end
112
+
113
+ def test_reads_utf16be
114
+ formatter = prepare_mock_formatter DummyFormatter
115
+ new_runner(fixture_path('enc_utf16be.dummy'), 'UTF-16BE').consume_string_file
116
+ assert_equal @expected_content, formatter.content
117
+ end
118
+ end
53
119
  end
@@ -41,8 +41,8 @@ class TestAndroidFormatter < FormatterTest
41
41
  super Twine::Formatters::Android
42
42
  end
43
43
 
44
- def test_read_file_format
45
- @formatter.read_file fixture('formatter_android.xml'), 'en'
44
+ def test_read_format
45
+ @formatter.read content_io('formatter_android.xml'), 'en'
46
46
 
47
47
  assert_file_contents_read_correctly
48
48
  end
@@ -67,11 +67,10 @@ class TestAndroidFormatter < FormatterTest
67
67
  assert_equal '@value', @strings.strings_map['key1'].translations['en']
68
68
  end
69
69
 
70
- def test_write_file_output_format
70
+ def test_format_file
71
71
  formatter = Twine::Formatters::Android.new
72
72
  formatter.strings = @twine_file
73
- formatter.write_file @output_path, 'en'
74
- assert_equal content('formatter_android.xml'), output_content
73
+ assert_equal content('formatter_android.xml'), formatter.format_file('en')
75
74
  end
76
75
 
77
76
  def test_format_key_with_space
@@ -100,6 +99,31 @@ class TestAndroidFormatter < FormatterTest
100
99
  identifier = '@android:string/cancel'
101
100
  assert_equal identifier, @formatter.format_value(identifier)
102
101
  end
102
+
103
+ def test_deducts_language_from_resource_folder
104
+ language = %w(en de fr).sample
105
+ assert_equal language, @formatter.determine_language_given_path("res/values-#{language}")
106
+ end
107
+
108
+ def test_deducts_language_and_region_from_resource_folder
109
+ assert_equal 'de-AT', @formatter.determine_language_given_path("res/values-de-rAT")
110
+ end
111
+
112
+ def test_maps_laguage_deducted_from_resource_folder
113
+ assert_equal 'zh-Hans', @formatter.determine_language_given_path("res/values-zh-rCN")
114
+ end
115
+
116
+ def test_does_not_deduct_language_from_device_capability_resource_folder
117
+ assert_nil @formatter.determine_language_given_path('res/values-w820dp')
118
+ end
119
+
120
+ def test_output_path_is_prefixed
121
+ assert_equal 'values-en', @formatter.output_path_for_language('en')
122
+ end
123
+
124
+ def test_output_path_language_mappings
125
+ assert_equal 'values-zh-rCN', @formatter.output_path_for_language('zh-Hans')
126
+ end
103
127
  end
104
128
 
105
129
  class TestAppleFormatter < FormatterTest
@@ -107,17 +131,56 @@ class TestAppleFormatter < FormatterTest
107
131
  super Twine::Formatters::Apple
108
132
  end
109
133
 
110
- def test_read_file_format
111
- @formatter.read_file fixture('formatter_apple.strings'), 'en'
134
+ def test_read_format
135
+ @formatter.read content_io('formatter_apple.strings'), 'en'
112
136
 
113
137
  assert_file_contents_read_correctly
114
138
  end
115
139
 
116
- def test_write_file_output_format
140
+ def test_reads_quoted_keys
141
+ @formatter.read StringIO.new('"key" = "value"'), 'en'
142
+ assert_equal 'value', @strings.strings_map['key'].translations['en']
143
+ end
144
+
145
+ def test_reads_unquoted_keys
146
+ @formatter.read StringIO.new('key = "value"'), 'en'
147
+ assert_equal 'value', @strings.strings_map['key'].translations['en']
148
+ end
149
+
150
+ def test_ignores_leading_whitespace_before_quoted_keys
151
+ @formatter.read StringIO.new("\t \"key\" = \"value\""), 'en'
152
+ assert_equal 'value', @strings.strings_map['key'].translations['en']
153
+ end
154
+
155
+ def test_ignores_leading_whitespace_before_unquoted_keys
156
+ @formatter.read StringIO.new("\t key = \"value\""), 'en'
157
+ assert_equal 'value', @strings.strings_map['key'].translations['en']
158
+ end
159
+
160
+ def test_allows_quotes_in_quoted_keys
161
+ @formatter.read StringIO.new('"ke\"y" = "value"'), 'en'
162
+ assert_equal 'value', @strings.strings_map['ke"y'].translations['en']
163
+ end
164
+
165
+ def test_does_not_allow_quotes_in_quoted_keys
166
+ @formatter.read StringIO.new('ke"y = "value"'), 'en'
167
+ assert_nil @strings.strings_map['key']
168
+ end
169
+
170
+ def test_allows_equal_signs_in_quoted_keys
171
+ @formatter.read StringIO.new('"k=ey" = "value"'), 'en'
172
+ assert_equal 'value', @strings.strings_map['k=ey'].translations['en']
173
+ end
174
+
175
+ def test_does_not_allow_equal_signs_in_unquoted_keys
176
+ @formatter.read StringIO.new('k=ey = "value"'), 'en'
177
+ assert_nil @strings.strings_map['key']
178
+ end
179
+
180
+ def test_format_file
117
181
  formatter = Twine::Formatters::Apple.new
118
182
  formatter.strings = @twine_file
119
- formatter.write_file @output_path, 'en'
120
- assert_equal content('formatter_apple.strings'), output_content
183
+ assert_equal content('formatter_apple.strings'), formatter.format_file('en')
121
184
  end
122
185
 
123
186
  def test_format_key_with_space
@@ -139,17 +202,16 @@ class TestJQueryFormatter < FormatterTest
139
202
  super Twine::Formatters::JQuery
140
203
  end
141
204
 
142
- def test_read_file_format
143
- @formatter.read_file fixture('formatter_jquery.json'), 'en'
205
+ def test_read_format
206
+ @formatter.read content_io('formatter_jquery.json'), 'en'
144
207
 
145
208
  assert_translations_read_correctly
146
209
  end
147
210
 
148
- def test_write_file_output_format
211
+ def test_format_file
149
212
  formatter = Twine::Formatters::JQuery.new
150
213
  formatter.strings = @twine_file
151
- formatter.write_file @output_path, 'en'
152
- assert_equal content('formatter_jquery.json'), output_content
214
+ assert_equal content('formatter_jquery.json'), formatter.format_file('en')
153
215
  end
154
216
 
155
217
  def test_format_value_with_newline
@@ -163,23 +225,22 @@ class TestGettextFormatter < FormatterTest
163
225
  super Twine::Formatters::Gettext
164
226
  end
165
227
 
166
- def test_read_file_format
167
- @formatter.read_file fixture('formatter_gettext.po'), 'en'
228
+ def test_read_format
229
+ @formatter.read content_io('formatter_gettext.po'), 'en'
168
230
 
169
231
  assert_file_contents_read_correctly
170
232
  end
171
233
 
172
- def test_read_file_with_multiple_line_value
173
- @formatter.read_file fixture('gettext_multiline.po'), 'en'
234
+ def test_read_with_multiple_line_value
235
+ @formatter.read content_io('gettext_multiline.po'), 'en'
174
236
 
175
237
  assert_equal 'multiline\nstring', @strings.strings_map['key1'].translations['en']
176
238
  end
177
239
 
178
- def test_write_file_output_format
240
+ def test_format_file
179
241
  formatter = Twine::Formatters::Gettext.new
180
242
  formatter.strings = @twine_file
181
- formatter.write_file @output_path, 'en'
182
- assert_equal content('formatter_gettext.po'), output_content
243
+ assert_equal content('formatter_gettext.po'), formatter.format_file('en')
183
244
  end
184
245
 
185
246
  end
@@ -190,18 +251,17 @@ class TestTizenFormatter < FormatterTest
190
251
  super Twine::Formatters::Tizen
191
252
  end
192
253
 
193
- def test_read_file_format
194
- skip 'the current implementation of Tizen formatter does not support read_file'
195
- @formatter.read_file fixture('formatter_tizen.xml'), 'en'
254
+ def test_read_format
255
+ skip 'the current implementation of Tizen formatter does not support reading'
256
+ @formatter.read content_io('formatter_tizen.xml'), 'en'
196
257
 
197
258
  assert_file_contents_read_correctly
198
259
  end
199
260
 
200
- def test_write_file_output_format
261
+ def test_format_file
201
262
  formatter = Twine::Formatters::Tizen.new
202
263
  formatter.strings = @twine_file
203
- formatter.write_file @output_path, 'en'
204
- assert_equal content('formatter_tizen.xml'), output_content
264
+ assert_equal content('formatter_tizen.xml'), formatter.format_file('en')
205
265
  end
206
266
 
207
267
  end
@@ -211,17 +271,16 @@ class TestDjangoFormatter < FormatterTest
211
271
  super Twine::Formatters::Django
212
272
  end
213
273
 
214
- def test_read_file_format
215
- @formatter.read_file fixture('formatter_django.po'), 'en'
274
+ def test_read_format
275
+ @formatter.read content_io('formatter_django.po'), 'en'
216
276
 
217
277
  assert_file_contents_read_correctly
218
278
  end
219
279
 
220
- def test_write_file_output_format
280
+ def test_format_file
221
281
  formatter = Twine::Formatters::Django.new
222
282
  formatter.strings = @twine_file
223
- formatter.write_file @output_path, 'en'
224
- assert_equal content('formatter_django.po'), output_content
283
+ assert_equal content('formatter_django.po'), formatter.format_file('en')
225
284
  end
226
285
  end
227
286
 
@@ -230,16 +289,15 @@ class TestFlashFormatter < FormatterTest
230
289
  super Twine::Formatters::Flash
231
290
  end
232
291
 
233
- def test_read_file_format
234
- @formatter.read_file fixture('formatter_flash.properties'), 'en'
292
+ def test_read_format
293
+ @formatter.read content_io('formatter_flash.properties'), 'en'
235
294
 
236
295
  assert_file_contents_read_correctly
237
296
  end
238
297
 
239
- def test_write_file_output_format
298
+ def test_format_file
240
299
  formatter = Twine::Formatters::Flash.new
241
300
  formatter.strings = @twine_file
242
- formatter.write_file @output_path, 'en'
243
- assert_equal content('formatter_flash.properties'), output_content
301
+ assert_equal content('formatter_flash.properties'), formatter.format_file('en')
244
302
  end
245
303
  end
@@ -1,48 +1,74 @@
1
1
  require 'command_test_case'
2
2
 
3
3
  class TestGenerateAllStringFiles < CommandTestCase
4
- class TestCreateFolders < CommandTestCase
5
- def new_runner(create_folders)
6
- options = {}
7
- options[:output_path] = @output_dir
8
- options[:format] = 'apple'
9
- options[:create_folders] = create_folders
4
+ def new_runner(create_folders, twine_file = nil)
5
+ options = {}
6
+ options[:output_path] = @output_dir
7
+ options[:format] = 'apple'
8
+ options[:create_folders] = create_folders
10
9
 
10
+ unless twine_file
11
11
  twine_file = build_twine_file 'en', 'es' do
12
12
  add_section 'Section' do
13
13
  add_row key: 'value'
14
14
  end
15
15
  end
16
+ end
16
17
 
17
- Twine::Runner.new(options, twine_file)
18
+ Twine::Runner.new(options, twine_file)
19
+ end
20
+
21
+ class TestDoNotCreateFolders < TestGenerateAllStringFiles
22
+ def new_runner(twine_file = nil)
23
+ super(false, twine_file)
18
24
  end
19
25
 
20
26
  def test_fails_if_output_folder_does_not_exist
21
27
  assert_raises Twine::Error do
22
- new_runner(false).generate_all_string_files
28
+ new_runner.generate_all_string_files
23
29
  end
24
30
  end
25
31
 
26
- def test_creates_output_folder
27
- FileUtils.remove_entry_secure @output_dir
28
- new_runner(true).generate_all_string_files
29
- assert File.exists? @output_dir
32
+ def test_does_not_create_language_folders
33
+ Dir.mkdir File.join @output_dir, 'en.lproj'
34
+ new_runner.generate_all_string_files
35
+ refute File.exists?(File.join(@output_dir, 'es.lproj')), "language folder should not be created"
30
36
  end
31
37
 
32
- def test_does_not_create_language_folders_by_default
38
+ def test_prints_empty_file_warnings
33
39
  Dir.mkdir File.join @output_dir, 'en.lproj'
34
- new_runner(false).generate_all_string_files
35
- refute File.exists?(File.join(@output_dir, 'es.lproj')), "language folder should not be created"
40
+ empty_twine_file = build_twine_file('en') {}
41
+ new_runner(empty_twine_file).generate_all_string_files
42
+ assert_match "Skipping file at path", Twine::stderr.string
43
+ end
44
+ end
45
+
46
+ class TestCreateFolders < TestGenerateAllStringFiles
47
+ def new_runner(twine_file = nil)
48
+ super(true, twine_file)
49
+ end
50
+
51
+ def test_creates_output_folder
52
+ FileUtils.remove_entry_secure @output_dir
53
+ new_runner.generate_all_string_files
54
+ assert File.exists? @output_dir
36
55
  end
37
56
 
38
57
  def test_creates_language_folders
39
- new_runner(true).generate_all_string_files
58
+ new_runner.generate_all_string_files
40
59
  assert File.exists?(File.join(@output_dir, 'en.lproj')), "language folder 'en.lproj' should be created"
41
60
  assert File.exists?(File.join(@output_dir, 'es.lproj')), "language folder 'es.lproj' should be created"
42
61
  end
62
+
63
+ def test_prints_empty_file_warnings
64
+ empty_twine_file = build_twine_file('en') {}
65
+ new_runner(empty_twine_file).generate_all_string_files
66
+
67
+ assert_match "Skipping file at path", Twine::stderr.string
68
+ end
43
69
  end
44
70
 
45
- class TestDeliberate < CommandTestCase
71
+ class TestValidate < CommandTestCase
46
72
  def new_runner(validate)
47
73
  Dir.mkdir File.join @output_dir, 'values-en'
48
74