forked from python-babel/babel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_js_extract.py
222 lines (174 loc) · 6.74 KB
/
test_js_extract.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
from io import BytesIO
import pytest
from babel.messages import extract
def test_simple_extract():
buf = BytesIO(b"""\
msg1 = _('simple')
msg2 = gettext('simple')
msg3 = ngettext('s', 'p', 42)
""")
messages = \
list(extract.extract('javascript', buf, extract.DEFAULT_KEYWORDS,
[], {}))
assert messages == [(1, 'simple', [], None),
(2, 'simple', [], None),
(3, ('s', 'p'), [], None)]
def test_various_calls():
buf = BytesIO(b"""\
msg1 = _(i18n_arg.replace(/"/, '"'))
msg2 = ungettext(i18n_arg.replace(/"/, '"'), multi_arg.replace(/"/, '"'), 2)
msg3 = ungettext("Babel", multi_arg.replace(/"/, '"'), 2)
msg4 = ungettext(i18n_arg.replace(/"/, '"'), "Babels", 2)
msg5 = ungettext('bunny', 'bunnies', parseInt(Math.random() * 2 + 1))
msg6 = ungettext(arg0, 'bunnies', rparseInt(Math.random() * 2 + 1))
msg7 = _(hello.there)
msg8 = gettext('Rabbit')
msg9 = dgettext('wiki', model.addPage())
msg10 = dngettext(domain, 'Page', 'Pages', 3)
""")
messages = \
list(extract.extract('javascript', buf, extract.DEFAULT_KEYWORDS, [],
{}))
assert messages == [
(5, ('bunny', 'bunnies'), [], None),
(8, 'Rabbit', [], None),
(10, ('Page', 'Pages'), [], None)
]
def test_message_with_line_comment():
buf = BytesIO("""\
// NOTE: hello
msg = _('Bonjour à tous')
""".encode('utf-8'))
messages = list(extract.extract_javascript(buf, ('_',), ['NOTE:'], {}))
assert messages[0][2] == 'Bonjour à tous'
assert messages[0][3] == ['NOTE: hello']
def test_message_with_multiline_comment():
buf = BytesIO("""\
/* NOTE: hello
and bonjour
and servus */
msg = _('Bonjour à tous')
""".encode('utf-8'))
messages = list(extract.extract_javascript(buf, ('_',), ['NOTE:'], {}))
assert messages[0][2] == 'Bonjour à tous'
assert messages[0][3] == ['NOTE: hello', 'and bonjour', ' and servus']
def test_ignore_function_definitions():
buf = BytesIO(b"""\
function gettext(value) {
return translations[language][value] || value;
}""")
messages = list(extract.extract_javascript(buf, ('gettext',), [], {}))
assert not messages
def test_misplaced_comments():
buf = BytesIO(b"""\
/* NOTE: this won't show up */
foo()
/* NOTE: this will */
msg = _('Something')
// NOTE: this will show up
// too.
msg = _('Something else')
// NOTE: but this won't
bar()
_('no comment here')
""")
messages = list(extract.extract_javascript(buf, ('_',), ['NOTE:'], {}))
assert messages[0][2] == 'Something'
assert messages[0][3] == ['NOTE: this will']
assert messages[1][2] == 'Something else'
assert messages[1][3] == ['NOTE: this will show up', 'too.']
assert messages[2][2] == 'no comment here'
assert messages[2][3] == []
JSX_SOURCE = b"""
class Foo {
render() {
const value = gettext("hello");
return (
<option value="val1">{ i18n._('String1') }</option>
<option value="val2">{ i18n._('String 2') }</option>
<option value="val3">{ i18n._('String 3') }</option>
<option value="val4">{ _('String 4') }</option>
<option>{ _('String 5') }</option>
);
}
"""
EXPECTED_JSX_MESSAGES = ["hello", "String1", "String 2", "String 3", "String 4", "String 5"]
@pytest.mark.parametrize("jsx_enabled", (False, True))
def test_jsx_extraction(jsx_enabled):
buf = BytesIO(JSX_SOURCE)
messages = [m[2] for m in extract.extract_javascript(buf, ('_', 'gettext'), [], {"jsx": jsx_enabled})]
if jsx_enabled:
assert messages == EXPECTED_JSX_MESSAGES
else:
assert messages != EXPECTED_JSX_MESSAGES
def test_dotted_keyword_extract():
buf = BytesIO(b"msg1 = com.corporate.i18n.formatMessage('Insert coin to continue')")
messages = list(
extract.extract('javascript', buf, {"com.corporate.i18n.formatMessage": None}, [], {})
)
assert messages == [(1, 'Insert coin to continue', [], None)]
def test_template_string_standard_usage():
buf = BytesIO(b"msg1 = gettext(`Very template, wow`)")
messages = list(
extract.extract('javascript', buf, {"gettext": None}, [], {})
)
assert messages == [(1, 'Very template, wow', [], None)]
def test_template_string_tag_usage():
buf = BytesIO(b"function() { if(foo) msg1 = i18n`Tag template, wow`; }")
messages = list(
extract.extract('javascript', buf, {"i18n": None}, [], {})
)
assert messages == [(1, 'Tag template, wow', [], None)]
def test_inside_template_string():
buf = BytesIO(b"const msg = `${gettext('Hello')} ${user.name}`")
messages = list(
extract.extract('javascript', buf, {"gettext": None}, [], {'parse_template_string': True})
)
assert messages == [(1, 'Hello', [], None)]
def test_inside_template_string_with_linebreaks():
buf = BytesIO(b"""\
const userName = gettext('Username')
const msg = `${
gettext('Hello')
} ${userName} ${
gettext('Are you having a nice day?')
}`
const msg2 = `${
gettext('Howdy')
} ${userName} ${
gettext('Are you doing ok?')
}`
""")
messages = list(
extract.extract('javascript', buf, {"gettext": None}, [], {'parse_template_string': True})
)
assert messages == [(1, 'Username', [], None), (3, 'Hello', [], None), (5, 'Are you having a nice day?', [], None), (8, 'Howdy', [], None), (10, 'Are you doing ok?', [], None)]
def test_inside_nested_template_string():
buf = BytesIO(b"const msg = `${gettext('Greetings!')} ${ evening ? `${user.name}: ${gettext('This is a lovely evening.')}` : `${gettext('The day is really nice!')} ${user.name}`}`")
messages = list(
extract.extract('javascript', buf, {"gettext": None}, [], {'parse_template_string': True})
)
assert messages == [(1, 'Greetings!', [], None), (1, 'This is a lovely evening.', [], None), (1, 'The day is really nice!', [], None)]
def test_regex_with_non_escaped_slash():
"""
Test if regexes with non-escaped slashes are parsed correctly.
A Javascript regex that is opened and closed with slashes, allows a
non-escaped slash inside a character class, like: [/]. In the past, the
babel JS lexer thought this closed the regex.
If a " followed the falsly closing /, then babel thought a javascript
string was started, and would stretch it to the next quote. This caused the
bug.
The regex in babel/messages/jslexer.py now covers this scenario, and this
unit test makes sure it works.
"""
buf = BytesIO(b"""\
msg1 = _('message 1')
regex1 = /[/]"/
msg2 = _('message 2')
fake_closing_quote = '"'
""")
messages = \
list(extract.extract('javascript', buf, extract.DEFAULT_KEYWORDS,
[], {}))
assert messages == [(1, 'message 1', [], None),
(3, 'message 2', [], None)]