Skip to content

Commit 8e42b21

Browse files
committed
Fixed bug in JS literal serialization that accidentally serialized strings as dicts. Closes #130
1 parent 10e6a40 commit 8e42b21

File tree

4 files changed

+56
-8
lines changed

4 files changed

+56
-8
lines changed

highcharts_core/js_literal_functions.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,25 @@ def is_js_object(as_str, careful_validation = False):
159159
is_empty = as_str[1:-1].strip() == ''
160160
if is_empty:
161161
return True
162-
has_colon = ':' in as_str
163-
if has_colon:
164-
return True
165-
if 'new ' in as_str:
162+
colon_count = as_str.count(':')
163+
open_brace_count = as_str.count('{')
164+
close_brace_count = as_str.count('}')
165+
brace_set_count = (open_brace_count + close_brace_count) / 2
166+
if colon_count > 0:
167+
if brace_set_count == 1:
168+
return True
169+
elif brace_set_count > 1 and colon_count >= brace_set_count:
170+
return True
171+
else:
172+
careful_validation = True
173+
elif 'new ' in as_str:
166174
return True
167-
if 'Object.create(' in as_str:
175+
elif 'Object.create(' in as_str:
168176
return True
169-
return False
170-
else:
177+
else:
178+
return False
179+
180+
if careful_validation:
171181
expression_item = f'const testName = {as_str}'
172182
try:
173183
parsed = esprima.parseScript(expression_item)
@@ -192,6 +202,8 @@ def is_js_object(as_str, careful_validation = False):
192202
return True
193203

194204
return False
205+
206+
return False
195207

196208

197209
def attempt_variable_declaration(as_str):

tests/fixtures.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ def Class_from_js_literal(cls, input_files, filename, as_file, error):
796796
assert isinstance(result, cls) is True
797797

798798
as_js_literal = result.to_js_literal()
799+
print(as_js_literal)
799800
#print('-----------------')
800801
#print('RESULT VALIDATION')
801802
if 'pattern:' in as_js_literal:

tests/options/test_tooltips.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from highcharts_core import errors
1010
from tests.fixtures import input_files, check_input_file, to_camelCase, to_js_dict, \
1111
Class__init__, Class__to_untrimmed_dict, Class_from_dict, Class_to_dict, \
12-
Class_from_js_literal
12+
Class_from_js_literal, compare_js_literals
1313

1414
STANDARD_PARAMS = [
1515
({}, None),
@@ -86,6 +86,9 @@
8686
}""",
8787
'split': True
8888
}, None),
89+
({
90+
'format': '{point.name} {point.y}'
91+
}, None),
8992

9093
({
9194
'border_width': 'not-a-number'
@@ -128,3 +131,17 @@ def test_to_dict(kwargs, error):
128131
])
129132
def test_from_js_literal(input_files, filename, as_file, error):
130133
Class_from_js_literal(cls, input_files, filename, as_file, error)
134+
135+
136+
def test_bug130_tooltip_serialization():
137+
as_js_literal = """{
138+
format: '{point.name}: {point.y}'
139+
}"""
140+
141+
obj = cls.from_js_literal(as_js_literal)
142+
assert obj is not None
143+
assert isinstance(obj, cls) is True
144+
assert obj.format == '{point.name}: {point.y}'
145+
146+
result = obj.to_js_literal()
147+
assert "'{point.name}: {point.y}'" in result or '"{point.name}: {point.y}"' in result

tests/test_js_literal_functions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,21 @@ def test_convert_js_property_to_python(original_str, override, expected, error):
190190
else:
191191
with pytest.raises(error):
192192
result = js.convert_js_property_to_python(item, original_str)
193+
194+
195+
@pytest.mark.parametrize('original_str, expected, error', [
196+
("Object.create({item1:true})", True, None),
197+
("new Date()", True, None),
198+
("test string", False, None),
199+
("{item1: 456}", True, None),
200+
("'{point.name}: {point.y}'", False, None),
201+
("{item: {subitem: 123}}", True, None),
202+
("{item: 123, item2: 456, item3: {subitem: 789}}", True, None),
203+
])
204+
def test_is_js_object(original_str, expected, error):
205+
if not error:
206+
result = js.is_js_object(original_str)
207+
assert result is expected
208+
else:
209+
with pytest.raises(error):
210+
result = js.is_js_object(original_str)

0 commit comments

Comments
 (0)