|
|
@@ -0,0 +1,300 @@ |
|
|
|
import parse |
|
|
|
import testdata |
|
|
|
import unittest |
|
|
|
import unittest.mock |
|
|
|
|
|
|
|
|
|
|
|
class TestCase(unittest.TestCase): |
|
|
|
''' |
|
|
|
Base test case class |
|
|
|
''' |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
''' |
|
|
|
Overwrite the standard string representation by an easier to read version. |
|
|
|
''' |
|
|
|
# Based on http://stackoverflow.com/a/18460031 |
|
|
|
return '.'.join([self.__class__.__module__, self.__class__.__name__, self._testMethodName]) |
|
|
|
|
|
|
|
def shortDescription(self): |
|
|
|
''' |
|
|
|
Disable displaying the first line of the docstring instead of module.class.method. |
|
|
|
''' |
|
|
|
# http://www.saltycrane.com/blog/2012/07/how-prevent-nose-unittest-using-docstring-when-verbosity-2/ |
|
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
class TestStrEnum(TestCase): |
|
|
|
def test_clean_representation(self): |
|
|
|
self.assertEqual(repr(parse.Type.group), 'Type.group') |
|
|
|
self.assertEqual(repr(parse.Type.brackets), 'Type.brackets') |
|
|
|
self.assertEqual(repr(parse.Modifier.negate), 'Modifier.negate') |
|
|
|
self.assertEqual(repr(parse.Modifier.plus), 'Modifier.plus') |
|
|
|
|
|
|
|
|
|
|
|
class TestJSTypes(TestCase): |
|
|
|
def test_equality(self): |
|
|
|
self.assertEqual(parse.JSBool(True), parse.JSBool(True)) |
|
|
|
self.assertEqual(parse.JSBool(False), parse.JSBool(False)) |
|
|
|
self.assertNotEqual(parse.JSBool(True), parse.JSBool(False)) |
|
|
|
self.assertNotEqual(parse.JSBool(False), parse.JSBool(True)) |
|
|
|
|
|
|
|
self.assertEqual(parse.JSInt(0), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSInt(42), parse.JSInt(42)) |
|
|
|
self.assertEqual(parse.JSInt(-13), parse.JSInt(-13)) |
|
|
|
self.assertNotEqual(parse.JSInt(0), parse.JSInt(42)) |
|
|
|
self.assertNotEqual(parse.JSInt(42), parse.JSInt(0)) |
|
|
|
self.assertNotEqual(parse.JSInt(0), parse.JSInt(-13)) |
|
|
|
self.assertNotEqual(parse.JSInt(-13), parse.JSInt(42)) |
|
|
|
|
|
|
|
self.assertEqual(parse.JSString(''), parse.JSString('')) |
|
|
|
self.assertEqual(parse.JSString('test'), parse.JSString('test')) |
|
|
|
self.assertNotEqual(parse.JSString(''), parse.JSString('test')) |
|
|
|
|
|
|
|
# Comparisons between different types are currently not supported (JS's equality algorithm is a nightmare) and always return False |
|
|
|
self.assertNotEqual(parse.JSBool(True), parse.JSInt(1)) |
|
|
|
self.assertNotEqual(parse.JSBool(True), parse.JSString('true')) |
|
|
|
|
|
|
|
def test_operators(self): |
|
|
|
self.assertEqual(parse.JSBool(True) + parse.JSBool(True), parse.JSInt(2)) |
|
|
|
self.assertEqual(parse.JSBool(True) + parse.JSInt(41), parse.JSInt(42)) |
|
|
|
self.assertEqual(parse.JSBool(True) + parse.JSString('42'), parse.JSString('true42')) |
|
|
|
self.assertEqual(parse.JSBool(True) - parse.JSBool(True), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSBool(False) - parse.JSBool(True), parse.JSInt(-1)) |
|
|
|
self.assertEqual(parse.JSBool(True) - parse.JSInt(3), parse.JSInt(-2)) |
|
|
|
self.assertEqual(parse.JSBool(True) - parse.JSString('14'), parse.JSInt(-13)) |
|
|
|
self.assertEqual(parse.JSBool(True) - parse.JSString(''), parse.JSInt(1)) |
|
|
|
#self.assertEqual(parse.JSBool(True) - parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSBool(True) - parse.JSString('3test'), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSBool(True) * parse.JSBool(True), parse.JSInt(1)) |
|
|
|
self.assertEqual(parse.JSBool(False) * parse.JSBool(True), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSBool(True) * parse.JSInt(42), parse.JSInt(42)) |
|
|
|
self.assertEqual(parse.JSBool(False) * parse.JSInt(42), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSBool(True) * parse.JSString('13'), parse.JSInt(13)) |
|
|
|
self.assertEqual(parse.JSBool(True) * parse.JSString(''), parse.JSInt(0)) |
|
|
|
#self.assertEqual(parse.JSBool(True) * parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSBool(True) * parse.JSString('2test'), parse.JSInt(NaN)) # Not supported |
|
|
|
|
|
|
|
self.assertEqual(parse.JSInt(13) + parse.JSBool(True), parse.JSInt(14)) |
|
|
|
self.assertEqual(parse.JSInt(13) + parse.JSInt(29), parse.JSInt(42)) |
|
|
|
self.assertEqual(parse.JSInt(13) + parse.JSString('29'), parse.JSString('1329')) |
|
|
|
self.assertEqual(parse.JSInt(13) + parse.JSString(''), parse.JSString('13')) |
|
|
|
self.assertEqual(parse.JSInt(13) + parse.JSString('test'), parse.JSString('13test')) |
|
|
|
self.assertEqual(parse.JSInt(13) - parse.JSBool(True), parse.JSInt(12)) |
|
|
|
self.assertEqual(parse.JSInt(13) - parse.JSInt(12), parse.JSInt(1)) |
|
|
|
self.assertEqual(parse.JSInt(13) - parse.JSString('15'), parse.JSInt(-2)) |
|
|
|
self.assertEqual(parse.JSInt(13) - parse.JSString(''), parse.JSInt(13)) |
|
|
|
#self.assertEqual(parse.JSInt(13) - parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSInt(13) - parse.JSString('13test'), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSInt(3) * parse.JSBool(True), parse.JSInt(3)) |
|
|
|
self.assertEqual(parse.JSInt(3) * parse.JSInt(4), parse.JSInt(12)) |
|
|
|
self.assertEqual(parse.JSInt(3) * parse.JSString('4'), parse.JSInt(12)) |
|
|
|
self.assertEqual(parse.JSInt(3) * parse.JSString(''), parse.JSInt(0)) |
|
|
|
#self.assertEqual(parse.JSInt(3) * parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSInt(3) * parse.JSString('1test'), parse.JSInt(NaN)) # Not supported |
|
|
|
|
|
|
|
self.assertEqual(parse.JSString('1') + parse.JSBool(True), parse.JSString('1true')) |
|
|
|
self.assertEqual(parse.JSString('') + parse.JSBool(False), parse.JSString('false')) |
|
|
|
self.assertEqual(parse.JSString('test') + parse.JSBool(True), parse.JSString('testtrue')) |
|
|
|
self.assertEqual(parse.JSString('1') + parse.JSInt(1), parse.JSString('11')) |
|
|
|
self.assertEqual(parse.JSString('1') + parse.JSString('1'), parse.JSString('11')) |
|
|
|
self.assertEqual(parse.JSString('13') - parse.JSBool(True), parse.JSInt(12)) |
|
|
|
self.assertEqual(parse.JSString('') - parse.JSBool(True), parse.JSInt(-1)) |
|
|
|
#self.assertEqual(parse.JSString('test') - parse.JSBool(True), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('3test') - parse.JSBool(True), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSString('1') - parse.JSInt(3), parse.JSInt(-2)) |
|
|
|
self.assertEqual(parse.JSString('') - parse.JSInt(-3), parse.JSInt(3)) |
|
|
|
#self.assertEqual(parse.JSString('test') - parse.JSInt(13), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('13test') - parse.JSInt(13), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSString('13') - parse.JSString('2'), parse.JSInt(11)) |
|
|
|
self.assertEqual(parse.JSString('13') - parse.JSString(''), parse.JSInt(13)) |
|
|
|
self.assertEqual(parse.JSString('') - parse.JSString('-3'), parse.JSInt(3)) |
|
|
|
#self.assertEqual(parse.JSString('test') - parse.JSString('2'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('13test') - parse.JSString('2'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('2') - parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('2') - parse.JSString('13test'), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSString('3') * parse.JSBool(True), parse.JSInt(3)) |
|
|
|
self.assertEqual(parse.JSString('') * parse.JSBool(True), parse.JSInt(0)) |
|
|
|
#self.assertEqual(parse.JSString('test') * parse.JSBool(True), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('13test') * parse.JSBool(True), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSString('3') * parse.JSInt(2), parse.JSInt(6)) |
|
|
|
self.assertEqual(parse.JSString('') * parse.JSInt(13), parse.JSInt(0)) |
|
|
|
#self.assertEqual(parse.JSString('test') * parse.JSInt(1), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('13test') * parse.JSInt(1), parse.JSInt(NaN)) # Not supported |
|
|
|
self.assertEqual(parse.JSString('3') * parse.JSString('2'), parse.JSInt(6)) |
|
|
|
self.assertEqual(parse.JSString('3') * parse.JSString(''), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSString('') * parse.JSString('3'), parse.JSInt(0)) |
|
|
|
#self.assertEqual(parse.JSString('3') * parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('') * parse.JSString('test'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('test') * parse.JSString('3'), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('test') * parse.JSString(''), parse.JSInt(NaN)) # Not supported |
|
|
|
#self.assertEqual(parse.JSString('3test') * parse.JSString('3'), parse.JSInt(NaN)) # Not supported |
|
|
|
|
|
|
|
def test_casting(self): |
|
|
|
# Casting to Python objects |
|
|
|
self.assertEqual(bool(parse.JSBool(True)), True) |
|
|
|
self.assertEqual(bool(parse.JSBool(False)), False) |
|
|
|
self.assertEqual(int(parse.JSBool(True)), 1) |
|
|
|
self.assertEqual(int(parse.JSBool(False)), 0) |
|
|
|
self.assertEqual(str(parse.JSBool(True)), 'true') # JavaScript capitalisation! |
|
|
|
self.assertEqual(str(parse.JSBool(False)), 'false') |
|
|
|
|
|
|
|
self.assertEqual(bool(parse.JSInt(0)), False) |
|
|
|
self.assertEqual(bool(parse.JSInt(42)), True) |
|
|
|
self.assertEqual(int(parse.JSInt(0)), 0) |
|
|
|
self.assertEqual(int(parse.JSInt(42)), 42) |
|
|
|
self.assertEqual(str(parse.JSInt(0)), '0') |
|
|
|
self.assertEqual(str(parse.JSInt(42)), '42') |
|
|
|
|
|
|
|
self.assertEqual(bool(parse.JSString('')), False) |
|
|
|
self.assertEqual(bool(parse.JSString('test')), True) |
|
|
|
self.assertEqual(int(parse.JSString('')), 0) |
|
|
|
#self.assertEqual(int(parse.JSString('test')), NaN) # Not supported |
|
|
|
self.assertEqual(int(parse.JSString('0')), 0) |
|
|
|
self.assertEqual(int(parse.JSString('-13')), -13) |
|
|
|
self.assertEqual(str(parse.JSString('')), '') |
|
|
|
self.assertEqual(str(parse.JSString('test')), 'test') |
|
|
|
|
|
|
|
# Casting to JS types |
|
|
|
self.assertEqual(parse.JSBool(parse.JSBool(True)), parse.JSBool(True)) |
|
|
|
self.assertEqual(parse.JSBool(parse.JSBool(False)), parse.JSBool(False)) |
|
|
|
self.assertEqual(parse.JSInt(parse.JSBool(True)), parse.JSInt(1)) |
|
|
|
self.assertEqual(parse.JSInt(parse.JSBool(False)), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSString(parse.JSBool(True)), parse.JSString('true')) # JavaScript capitalisation! |
|
|
|
self.assertEqual(parse.JSString(parse.JSBool(False)), parse.JSString('false')) |
|
|
|
|
|
|
|
self.assertEqual(parse.JSBool(parse.JSInt(0)), parse.JSBool(False)) |
|
|
|
self.assertEqual(parse.JSBool(parse.JSInt(42)), parse.JSBool(True)) |
|
|
|
self.assertEqual(parse.JSInt(parse.JSInt(0)), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSInt(parse.JSInt(42)), parse.JSInt(42)) |
|
|
|
self.assertEqual(parse.JSString(parse.JSInt(0)), parse.JSString('0')) |
|
|
|
self.assertEqual(parse.JSString(parse.JSInt(42)), parse.JSString('42')) |
|
|
|
|
|
|
|
self.assertEqual(parse.JSBool(parse.JSString('')), parse.JSBool(False)) |
|
|
|
self.assertEqual(parse.JSBool(parse.JSString('test')), parse.JSBool(True)) |
|
|
|
#self.assertEqual(parse.JSInt(parse.JSString('')), parse.JSInt(0)) # Not supported (yet?) |
|
|
|
#self.assertEqual(parse.JSInt(parse.JSString('test')), parse.JSInt(NaN)) # Not supported (yet?) |
|
|
|
self.assertEqual(parse.JSInt(parse.JSString('0')), parse.JSInt(0)) |
|
|
|
self.assertEqual(parse.JSInt(parse.JSString('-13')), parse.JSInt(-13)) |
|
|
|
self.assertEqual(parse.JSString(parse.JSString('')), parse.JSString('')) |
|
|
|
self.assertEqual(parse.JSString(parse.JSString('test')), parse.JSString('test')) |
|
|
|
|
|
|
|
def test_repr(self): |
|
|
|
self.assertEqual(repr(parse.JSBool(True)), 'JSBool(True)') |
|
|
|
self.assertEqual(repr(parse.JSBool(False)), 'JSBool(False)') |
|
|
|
self.assertEqual(repr(parse.JSInt(0)), 'JSInt(0)') |
|
|
|
self.assertEqual(repr(parse.JSInt(-13)), 'JSInt(-13)') |
|
|
|
self.assertEqual(repr(parse.JSInt(42)), 'JSInt(42)') |
|
|
|
self.assertEqual(repr(parse.JSString('')), "JSString('')") |
|
|
|
self.assertEqual(repr(parse.JSString('test')), "JSString('test')") |
|
|
|
|
|
|
|
|
|
|
|
class TestItem(TestCase): |
|
|
|
def test_basic(self): |
|
|
|
item = parse.Item(parse.Type.group, [], values = []) |
|
|
|
item = parse.Item(parse.Type.group, [parse.Modifier.plus], values = []) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
parse.Item(-1, []) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
parse.Item(parse.Type.brackets, -1) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
parse.Item(parse.Type.brackets, [-1]) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
parse.Item(parse.Type.group, []) # no values |
|
|
|
|
|
|
|
def test_evaluate_brackets(self): |
|
|
|
def test_brackets(modifiers, result): |
|
|
|
self.assertEqual(parse.Item(parse.Type.brackets, modifiers).evaluate(), result) |
|
|
|
|
|
|
|
test_brackets([], parse.JSString('')) |
|
|
|
test_brackets([parse.Modifier.plus], parse.JSInt(0)) |
|
|
|
test_brackets([parse.Modifier.negate], parse.JSBool(False)) |
|
|
|
# ++[] -> syntax error |
|
|
|
test_brackets([parse.Modifier.plus, parse.Modifier.negate], parse.JSInt(0)) |
|
|
|
test_brackets([parse.Modifier.negate, parse.Modifier.plus], parse.JSBool(True)) |
|
|
|
test_brackets([parse.Modifier.negate, parse.Modifier.negate], parse.JSBool(True)) |
|
|
|
# +++[] -> syntax error |
|
|
|
# ++![] -> syntax error |
|
|
|
test_brackets([parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.plus], parse.JSInt(1)) |
|
|
|
test_brackets([parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate], parse.JSInt(1)) |
|
|
|
# !++[] -> syntax error |
|
|
|
test_brackets([parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate], parse.JSBool(True)) |
|
|
|
test_brackets([parse.Modifier.negate, parse.Modifier.negate, parse.Modifier.plus], parse.JSBool(False)) |
|
|
|
test_brackets([parse.Modifier.negate, parse.Modifier.negate, parse.Modifier.negate], parse.JSBool(False)) |
|
|
|
|
|
|
|
def test_evaluate_group(self): |
|
|
|
item = parse.Item(parse.Type.group, [], values = []) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
item.evaluate() # No evaluateFunction specified |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
item.evaluate(13) # Not a callable |
|
|
|
|
|
|
|
mock = unittest.mock.Mock(return_value = 42) |
|
|
|
item = parse.Item(parse.Type.group, [], values = [parse.Item(parse.Type.brackets, [parse.Modifier.plus])]) |
|
|
|
self.assertEqual(item.evaluate(evaluateFunction = mock), 42) |
|
|
|
self.assertEqual(mock.call_count, 1) |
|
|
|
self.assertEqual(len(mock.call_args), 2) |
|
|
|
self.assertEqual(len(mock.call_args[0]), 2) |
|
|
|
self.assertEqual(len(mock.call_args[1]), 0) |
|
|
|
self.assertIs(mock.call_args[0][0], item.values) |
|
|
|
self.assertIs(mock.call_args[0][1], item.modifiers) |
|
|
|
|
|
|
|
|
|
|
|
class TestFunctions(TestCase): |
|
|
|
def test_parse(self): |
|
|
|
self.assertEqual(parse.parse('!![]'), [parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate])]) |
|
|
|
self.assertEqual(parse.parse('!![]+!+![]'), [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate]), |
|
|
|
]) |
|
|
|
self.assertEqual(parse.parse('(!![]+!+![]+[])+(+!![]+[])'), [ |
|
|
|
parse.Item(parse.Type.group, [], [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), |
|
|
|
parse.Item(parse.Type.group, [], [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), |
|
|
|
]) |
|
|
|
self.assertEqual(parse.parse('+((!![]+!+![]+[])+(+!![]+[]))'), [ |
|
|
|
parse.Item(parse.Type.group, [parse.Modifier.plus], values = [ |
|
|
|
parse.Item(parse.Type.group, [], values = [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.plus, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), |
|
|
|
parse.Item(parse.Type.group, [], values = [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), |
|
|
|
]), |
|
|
|
]) |
|
|
|
|
|
|
|
def test_evaluate(self): |
|
|
|
self.assertEqual(parse.evaluate([parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate])]), parse.JSBool(True)) |
|
|
|
self.assertEqual(parse.evaluate([ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
]), parse.JSInt(2)) |
|
|
|
self.assertEqual(parse.evaluate([ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), parse.JSString('2')) |
|
|
|
self.assertEqual(parse.evaluate([ |
|
|
|
parse.Item(parse.Type.group, [], values = [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), |
|
|
|
parse.Item(parse.Type.group, [], values = [ |
|
|
|
parse.Item(parse.Type.brackets, [parse.Modifier.plus, parse.Modifier.negate, parse.Modifier.negate]), |
|
|
|
parse.Item(parse.Type.brackets, []), |
|
|
|
]), |
|
|
|
]), parse.JSString('21')) |
|
|
|
|
|
|
|
def test_crack(self): |
|
|
|
for url, html, result in testdata.data: |
|
|
|
self.assertEqual(parse.crack(url, html), parse.JSInt(result)) |