Merge pull request #1566 from zilioti/core-options-test

Add unit tests for core options
This commit is contained in:
Liam Newman 2018-10-08 10:46:02 -07:00 committed by GitHub
commit 7b20e88323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 320 additions and 21 deletions

View File

@ -29,8 +29,7 @@
'use strict';
function Options(options, merge_child_field) {
options = _mergeOpts(options, merge_child_field);
this.raw_options = _normalizeOpts(options);
this.raw_options = _mergeOpts(options, merge_child_field);
// Support passing the source text back with no change
this.disabled = this._get_boolean('disabled');
@ -141,10 +140,10 @@ Options.prototype._is_valid_selection = function(result, selection_list) {
// Example: obj = {a: 1, b: {a: 2}}
// mergeOpts(obj, 'b')
//
// Returns: {a: 2, b: {a: 2}}
// Returns: {a: 2}
function _mergeOpts(allOptions, childFieldName) {
var finalOpts = {};
allOptions = allOptions || {};
allOptions = _normalizeOpts(allOptions);
var name;
for (name in allOptions) {

View File

@ -0,0 +1,150 @@
/*jshint mocha:true */
'use strict';
var assert = require('assert');
var options = require('../../src/core/options');
describe('Options', function() {
describe('mergeOpts', function() {
it('should merge child option a with the parent options', function() {
assert.deepEqual(options.mergeOpts({
a: 1,
b: { a: 2 }
}, 'b'), {
a: 2
});
});
it('should include child option c and d with the parent options', function() {
assert.deepEqual(options.mergeOpts({
a: 1,
b: { c: 2, d: 3 }
}, 'b'), {
a: 1,
c: 2,
d: 3
});
});
it('should merge child option a and include c with the parent options', function() {
assert.deepEqual(options.mergeOpts({
a: 1,
b: { a: 2, c: 3 }
}, 'b'), {
a: 2,
c: 3
});
});
});
describe('normalizeOpts', function() {
it('should replace key with - to _', function() {
assert.deepEqual(options.normalizeOpts({
'a-b': 1
}), {
a_b: 1
});
});
it('should do nothing', function() {
assert.deepEqual(options.mergeOpts({
a: 1,
b_c: 2
}, 'b'), {
a: 1,
b_c: 2
});
});
});
describe('_get_boolean', function() {
it('should return false with no option and no default', function() {
assert.equal(new options.Options()._get_boolean(), false);
});
it('should return true as default since no option', function() {
assert.equal(new options.Options()._get_boolean('a', true), true);
});
it('should return false as in option', function() {
assert.equal(new options.Options({ a: false })._get_boolean('a', true), false);
});
});
describe('_get_characters', function() {
it('should return \'\' with no option', function() {
assert.equal(new options.Options()._get_characters(), '');
});
it('should return \'character\' as default since no option', function() {
assert.equal(new options.Options()._get_characters('a', 'character'), 'character');
});
it('should return \'char\' as in option', function() {
assert.equal(new options.Options({ a: 'char' })._get_characters('a', 'character'), 'char');
});
});
describe('_get_number', function() {
it('should return 0 with no option', function() {
assert.equal(new options.Options()._get_number(), 0);
});
it('should return 1 as default since no option', function() {
assert.equal(new options.Options()._get_number('a', 1), 1);
});
it('should return 10 as in option', function() {
assert.equal(new options.Options({ a: 10 })._get_number('a', 1), 10);
});
it('should return 0 for NaN as in option', function() {
assert.equal(new options.Options({ a: 'abc' })._get_number('a'), 0);
});
it('should return 0 for NaN as in default', function() {
assert.equal(new options.Options()._get_number('a', 'abc'), 0);
});
});
describe('_get_array', function() {
it('should return [] with no option', function() {
assert.deepEqual(new options.Options()._get_array(), []);
});
it('should return [\'a\',\'b\'] as default since no option', function() {
assert.deepEqual(new options.Options()._get_array('a', ['a', 'b']), ['a', 'b']);
});
it('should return [\'c\',\'d\'] as in option', function() {
assert.deepEqual(new options.Options({ a: ['c', 'd'] })._get_array('a', ['a', 'b']), ['c', 'd']);
});
it('should return [\'c\',\'d\'] as in option comma separated', function() {
assert.deepEqual(new options.Options({ a: 'c,d' })._get_array('a', ['a', 'b']), ['c', 'd']);
});
});
describe('_is_valid_selection', function() {
it('should return false with empty selection', function() {
assert.equal(new options.Options()._is_valid_selection(['a', 'b'], []), false);
});
it('should return false with selection inexistent', function() {
assert.equal(new options.Options()._is_valid_selection(['a', 'b'], ['c']), false);
});
it('should return true with selection existent', function() {
assert.equal(new options.Options()._is_valid_selection(['a', 'b'], ['a', 'b']), true);
});
});
describe('_get_selection_list', function() {
it('should throw error with empty selection', function() {
assert.throws(new options.Options()._get_selection_list, /^Error: Selection list cannot be empty.$/);
});
it('should throw error with invalid default', function() {
assert.throws(function() { new options.Options()._get_selection_list('a', ['a', 'b'], ['c']); }, /^Error: Invalid Default Value!$/);
});
it('should throw error with invalid option', function() {
assert.throws(function() { new options.Options({ a: ['c', 'd'] })._get_selection_list('a', ['a', 'b'], ['a']); }, /^Error: Invalid Option Value: The option/);
});
it('should return [\'a\'] as in option', function() {
assert.deepEqual(new options.Options({ a: ['a'] })._get_selection_list('a', ['a', 'b'], ['a']), ['a']);
});
});
describe('_get_selection', function() {
it('should throw error with multiple selection', function() {
assert.throws(function() { new options.Options({ a: ['a', 'b'] })._get_selection('a', ['a', 'b'], ['a']); }, /^Error: Invalid Option Value: The option/);
});
it('should return \'a\' as in option ', function() {
assert.equal(new options.Options({ a: ['a'] })._get_selection('a', ['a', 'b'], ['a']), 'a');
});
});
});

View File

@ -26,14 +26,14 @@ import copy
import re
from collections import namedtuple
class Options:
def __init__(self, options=None, merge_child_field=None):
self.css = None
self.js = None
self.html = None
options = _mergeOpts(options, merge_child_field)
self.raw_options = _normalizeOpts(options)
self.raw_options = _mergeOpts(options, merge_child_field)
# Support passing the source text back with no change
self.disabled = self._get_boolean('disabled')
@ -46,7 +46,8 @@ class Options:
self.preserve_newlines = self._get_boolean('preserve_newlines', True)
# TODO: fix difference in js and python
self.max_preserve_newlines = self.max_preserve_newlines = self._get_number('max_preserve_newlines', 10)
self.max_preserve_newlines = self._get_number(
'max_preserve_newlines', 10)
if not self.preserve_newlines:
self.max_preserve_newlines = 0
@ -56,7 +57,8 @@ class Options:
self.indent_size = 1
# Backwards compat with 1.3.x
self.wrap_line_length = self._get_number('wrap_line_length', self._get_number('max_char'))
self.wrap_line_length = self._get_number(
'wrap_line_length', self._get_number('max_char'))
def _get_array(self, name, default_value=[]):
option_value = getattr(self.raw_options, name, default_value)
@ -82,7 +84,8 @@ class Options:
option_value = getattr(self.raw_options, name, default_value)
result = ''
if isinstance(option_value, str):
result = option_value.replace('\\r', '\r').replace('\\n', '\n').replace('\\t', '\t')
result = option_value.replace('\\r', '\r').replace(
'\\n', '\n').replace('\\t', '\t')
return result
@ -108,7 +111,6 @@ class Options:
return result[0]
def _get_selection_list(self, name, selection_list, default_value=None):
if not selection_list:
raise ValueError("Selection list cannot be empty.")
@ -144,7 +146,7 @@ class Options:
# Example: obj = {a: 1, b: {a: 2}}
# mergeOpts(obj, 'b')
#
# Returns: {a: 2, b: {a: 2}}
# Returns: {a: 2}
def _mergeOpts(options, childFieldName):
@ -154,20 +156,27 @@ def _mergeOpts(options, childFieldName):
if isinstance(options, tuple):
options = dict(options)
if isinstance(options, dict):
options = _normalizeOpts(options)
options = namedtuple("CustomOptions", options.keys())(*options.values())
options = _normalizeOpts(options)
finalOpts = copy.copy(options)
if isinstance(options, dict):
local = finalOpts.get(childFieldName, None)
if local:
del(finalOpts[childFieldName])
for key in local:
finalOpts[key] = local[key]
finalOpts = namedtuple("CustomOptions", finalOpts.keys())(
*finalOpts.values())
local = getattr(finalOpts, childFieldName, None)
if local:
delattr(finalOpts, childFieldName)
for key in local:
setattr(finalOpts, key, local[key])
if isinstance(options, Options):
local = getattr(finalOpts, childFieldName, None)
if local:
delattr(finalOpts, childFieldName)
for key in local:
setattr(finalOpts, key, local[key])
return finalOpts
def _normalizeOpts(options):
convertedOpts = copy.copy(options)
if isinstance(convertedOpts, dict):
@ -181,6 +190,7 @@ def _normalizeOpts(options):
for key in option_keys:
if '-' in key:
delattr(convertedOpts, key)
setattr(convertedOpts, key.replace('-', '_'), getattr(options, key, None))
setattr(convertedOpts, key.replace(
'-', '_'), getattr(options, key, None))
return convertedOpts

View File

@ -0,0 +1,140 @@
import re
import unittest
from ...core.options import _mergeOpts, _normalizeOpts, Options
class TestOptions(unittest.TestCase):
@classmethod
def setUpClass(cls):
pass
def test_mergeOpts(self):
# should convert tuple to dict and merge child with parent
result = _mergeOpts((('a', 1), ('b', {'a': 2})), 'b')
self.assertEqual(result.a, 2)
self.assertNotIn('b', result)
# should merge child option a with the parent options (dict)
result = _mergeOpts({'a': 1, 'b': {'a': 2}}, 'b')
self.assertEqual(result.a, 2)
self.assertNotIn('b', result)
# should include child option c and d with the parent options (dict)
result = _mergeOpts({'a': 1, 'b': {'c': 2, 'd': 3}}, 'b')
self.assertEqual(result.a, 1)
self.assertEqual(result.c, 2)
self.assertEqual(result.d, 3)
self.assertNotIn('b', result)
# should merge child option a and include c as parent options (dict)
result = _mergeOpts({'a': 1, 'b': {'a': 2, 'c': 3}}, 'b')
self.assertEqual(result.a, 2)
self.assertEqual(result.c, 3)
self.assertNotIn('b', result)
# should merge Options instance with child dict key
instance = Options()
instance.a = {'disabled': True}
result = _mergeOpts(instance, 'a')
self.assertEqual(result.disabled, True)
self.assertNotIn('a', list(getattr(result, '__dict__', {})))
def test_normalizeOpts(self):
# should replace key with - to _ in dict
result = _normalizeOpts({
'a-b': 1
})
self.assertEqual(result['a_b'], 1)
self.assertNotIn('a-b', result)
# should replace key with - to _ in Options instance
instance = Options()
setattr(instance, 'a-b', 1)
result = _normalizeOpts(instance)
self.assertEqual(result.a_b, 1)
self.assertNotIn('a-b', list(getattr(result, '__dict__', {})))
# should do nothing
result = _normalizeOpts({
'a_b': 1
})
self.assertEqual(result['a_b'], 1)
def test__get_boolean(self):
# should return default value since no option
self.assertEqual(Options()._get_boolean('a'), False)
# should return true as default since no option
self.assertEqual(Options()._get_boolean('a', True), True)
# should return false as in option
self.assertEqual(Options({'a': False})._get_boolean('a', True), False)
def test__get_characters(self):
# should return default value since no option
self.assertEqual(Options()._get_characters('a'), '')
# should return \'character\' as default since no option
self.assertEqual(Options()._get_characters(
'a', 'character'), 'character')
# should return \'char\' as in option
self.assertEqual(Options({'a': 'char'})._get_characters(
'a', 'character'), 'char')
def test__get_number(self):
# should return default value since no option
self.assertEqual(Options()._get_number('a'), 0)
# should return 1 as default since no option
self.assertEqual(Options()._get_number('a', 1), 1)
# should return 10 as in option
self.assertEqual(Options({'a': 10})._get_number('a', 1), 10)
# should return 0 for NaN as in option
self.assertEqual(Options({'a': 'abc'})._get_number('a'), 0)
# should return 0 for NaN as in default
self.assertEqual(Options()._get_number('a', 'abc'), 0)
def test__get_array(self):
# should return [] with no option
self.assertEqual(Options()._get_array('a'), [])
# should return [\'a\',\'b\'] as default since no option
self.assertEqual(Options()._get_array('a', ['a', 'b']), ['a', 'b'])
# should return [\'c\',\'d\'] as in option
self.assertEqual(Options({'a': ['c', 'd']})._get_array(
'a', ['a', 'b']), ['c', 'd'])
# should return [\'c\',\'d\'] as in option comma separated
self.assertEqual(Options({'a': 'c,d'})._get_array(
'a', ['a', 'b']), ['c', 'd'])
def test__is_valid_selection(self):
# should return false with empty selection
self.assertEqual(Options()._is_valid_selection(['a', 'b'], []), False)
# should return false with selection inexistent
self.assertEqual(Options()._is_valid_selection(
['a', 'b'], ['c']), False)
# should return true with selection existent
self.assertEqual(Options()._is_valid_selection(
['a', 'b'], ['a', 'b']), True)
def test__get_selection_list(self):
# should raise error with empty selection
with self.assertRaisesRegexp(ValueError, 'Selection list cannot'
+ ' be empty.'):
Options()._get_selection_list('a', [])
# should raise error with invalid default
with self.assertRaisesRegexp(ValueError, 'Invalid Default Value!'):
Options()._get_selection_list('a', ['a', 'b'], ['c'])
# should raise error with invalid option
with self.assertRaisesRegexp(ValueError, '^Invalid Option Value:'
+ ' The option'):
Options({'a': ['c', 'd']})._get_selection_list(
'a', ['a', 'b'], ['a', 'b'])
# should return [\'c\'] as in option
opts = Options({'c': ['c']})
self.assertEqual(opts._get_selection_list(
'c', ['c', 'd'], ['c']), ['c'])
def test__get_selection(self):
# should raise error with multiple selection
with self.assertRaisesRegexp(ValueError, '^Invalid Option'
+ ' Value: The option'):
Options({'a': ['a', 'b']})._get_selection('a', ['a', 'b'], ['a'])
# should return [\'a\'] as in option
options = Options({'a': ['a']})
self.assertEqual(options._get_selection(
'a', ['a', 'b'], ['a']), 'a')
if __name__ == '__main__':
unittest.main()